diff --git a/.gitignore b/.gitignore index 8fef53c..9c6faaf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -db +db.sqlite3 /media /bin /include diff --git a/django-jquery-file-upload/settings.py b/django-jquery-file-upload/settings.py index d7e49bd..eb0c0d2 100644 --- a/django-jquery-file-upload/settings.py +++ b/django-jquery-file-upload/settings.py @@ -1,49 +1,23 @@ -import os - -DEBUG = True -TEMPLATE_DEBUG = DEBUG - -SITE_ROOT = os.path.dirname(os.path.realpath(__file__)) - -ADMINS = ( - # ('Your Name', 'your_email@example.com'), -) - -MANAGERS = ADMINS +""" +Django settings for this project. -DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. - 'NAME': os.path.join(SITE_ROOT, 'db'), # Or path to database file if using sqlite3. - 'USER': '', # Not used with sqlite3. - 'PASSWORD': '', # Not used with sqlite3. - 'HOST': '', # Set to empty string for localhost. Not used with sqlite3. - 'PORT': '', # Set to empty string for default. Not used with sqlite3. - } -} +Generated by 'django-admin startproject' using Django 1.9. -# Local time zone for this installation. Choices can be found here: -# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name -# although not all choices may be available on all operating systems. -# On Unix systems, a value of None will cause Django to use the same -# timezone as the operating system. -# If running in a Windows environment this must be set to the same as your -# system time zone. -TIME_ZONE = 'America/Chicago' +For more information on this file, see +https://docs.djangoproject.com/en/1.9/topics/settings/ -# Language code for this installation. All choices can be found here: -# http://www.i18nguy.com/unicode/language-identifiers.html -LANGUAGE_CODE = 'en-us' +For the full list of settings and their values, see +https://docs.djangoproject.com/en/1.9/ref/settings/ +""" +import os -SITE_ID = 1 +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) -# If you set this to False, Django will make some optimizations so as not -# to load the internationalization machinery. -USE_I18N = True +# Make this unique, and don't share it with anybody. +SECRET_KEY = '9%$in^gpdaig@v3or_to&_z(=n)3)$f1mr3hf9e#kespy2ajlo' -# If you set this to False, Django will not format dates, numbers and -# calendars according to the current locale -USE_L10N = True +DEBUG = True # Absolute filesystem path to the directory that will hold user-uploaded files. # Example: "/home/media/media.lawrence.com/media/" @@ -69,11 +43,21 @@ # Examples: "http://foo.com/static/admin/", "/static/admin/". ADMIN_MEDIA_PREFIX = '/static/admin/' -# Additional locations of static files -STATICFILES_DIRS = ( - # Put strings here, like "/home/html/static" or "C:/www/django/static". - # Always use forward slashes, even on Windows. - # Don't forget to use absolute paths, not relative paths. +ADMINS = ( + # ('Your Name', 'your_email@example.com'), +) + +MANAGERS = ADMINS + +INSTALLED_APPS = ( + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.sites', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'django.contrib.admin', + 'fileupload', ) # List of finder classes that know how to find static files in @@ -81,17 +65,6 @@ STATICFILES_FINDERS = ( 'django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder', -# 'django.contrib.staticfiles.finders.DefaultStorageFinder', -) - -# Make this unique, and don't share it with anybody. -SECRET_KEY = '9%$in^gpdaig@v3or_to&_z(=n)3)$f1mr3hf9e#kespy2ajlo' - -# List of callables that know how to import templates from various sources. -TEMPLATE_LOADERS = ( - 'django.template.loaders.filesystem.Loader', - 'django.template.loaders.app_directories.Loader', -# 'django.template.loaders.eggs.Loader', ) MIDDLEWARE_CLASSES = ( @@ -105,25 +78,50 @@ ROOT_URLCONF = 'django-jquery-file-upload.urls' -TEMPLATE_DIRS = ( - # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". - # Always use forward slashes, even on Windows. - # Don't forget to use absolute paths, not relative paths. -) +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] -INSTALLED_APPS = ( - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.sites', - 'django.contrib.messages', - 'django.contrib.staticfiles', - 'fileupload', - # Uncomment the next line to enable the admin: - 'django.contrib.admin', - # Uncomment the next line to enable admin documentation: - # 'django.contrib.admindocs', -) +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), # Or path to database file if using sqlite3. + 'USER': '', # Not used with sqlite3. + 'PASSWORD': '', # Not used with sqlite3. + 'HOST': '', # Set to empty string for localhost. Not used with sqlite3. + 'PORT': '', # Set to empty string for default. Not used with sqlite3. + } +} + +# Password validation +# https://docs.djangoproject.com/en/1.9/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] # A sample logging configuration. The only tangible logging # performed by this configuration is to send an email to @@ -147,3 +145,17 @@ }, } } + +# Language code for this installation. All choices can be found here: +# http://www.i18nguy.com/unicode/language-identifiers.html +LANGUAGE_CODE = 'en-us' + +SITE_ID = 1 + +# If you set this to False, Django will make some optimizations so as not +# to load the internationalization machinery. +USE_I18N = True + +# If you set this to False, Django will not format dates, numbers and +# calendars according to the current locale +USE_L10N = True diff --git a/django-jquery-file-upload/urls.py b/django-jquery-file-upload/urls.py index 7072912..a3f0b97 100644 --- a/django-jquery-file-upload/urls.py +++ b/django-jquery-file-upload/urls.py @@ -1,25 +1,19 @@ from django.conf.urls import patterns, include, url from django.http import HttpResponseRedirect +from django.views.static import serve + # Uncomment the next two lines to enable the admin: from django.contrib import admin admin.autodiscover() -urlpatterns = patterns('', - # Examples: - # url(r'^$', 'upload.views.home', name='home'), - +urlpatterns = [ url(r'^$', lambda x: HttpResponseRedirect('/upload/new/')), url(r'^upload/', include('fileupload.urls')), - - # Uncomment the admin/doc line below to enable admin documentation: - # url(r'^admin/doc/', include('django.contrib.admindocs.urls')), - - # Uncomment the next line to enable the admin: url(r'^admin/', include(admin.site.urls)), -) +] from os.path import join, abspath, dirname -urlpatterns += patterns('', - (r'^media/(.*)$', 'django.views.static.serve', {'document_root': join(abspath(dirname(__file__)), 'media')}), -) +urlpatterns += [ + url(r'^media/(.*)$', serve, {'document_root': join(abspath(dirname(__file__)), 'media')}), +] diff --git a/fileupload/admin.py b/fileupload/admin.py index faa5cdc..7aff4e9 100644 --- a/fileupload/admin.py +++ b/fileupload/admin.py @@ -1,4 +1,5 @@ -from fileupload.models import Picture +from fileupload.models import File, SingleUseToken from django.contrib import admin -admin.site.register(Picture) \ No newline at end of file +admin.site.register(File) +admin.site.register(SingleUseToken) diff --git a/fileupload/migrations/0001_initial.py b/fileupload/migrations/0001_initial.py new file mode 100644 index 0000000..2808f90 --- /dev/null +++ b/fileupload/migrations/0001_initial.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9 on 2015-12-19 14:19 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone +import fileupload.models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='File', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('file', models.FileField(upload_to='')), + ('slug', models.SlugField(blank=True)), + ], + ), + migrations.CreateModel( + name='SingleUseToken', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('token', models.CharField(default=fileupload.models.get_new_token, max_length=200)), + ('create_date', models.DateTimeField(default=django.utils.timezone.now)), + ('expiry_date', models.DateTimeField(default=django.utils.timezone.now)), + ], + ), + migrations.AddField( + model_name='file', + name='token', + field=models.ForeignKey(blank=True, on_delete=django.db.models.deletion.CASCADE, to='fileupload.SingleUseToken'), + ), + ] diff --git a/fileupload/migrations/__init__.py b/fileupload/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/fileupload/models.py b/fileupload/models.py index f28d242..565ae06 100644 --- a/fileupload/models.py +++ b/fileupload/models.py @@ -1,16 +1,28 @@ -# encoding: utf-8 +import os +import uuid + from django.db import models +from django.utils import timezone + +def get_new_token(): + return uuid.uuid1() +# Create your models here. +class SingleUseToken(models.Model): + token = models.CharField(default=get_new_token, max_length=200) + create_date = models.DateTimeField(default=timezone.now) + expiry_date = models.DateTimeField(default=timezone.now) -class Picture(models.Model): +class File(models.Model): """This is a small demo using just two fields. The slug field is really not necessary, but makes the code simpler. ImageField depends on PIL or pillow (where Pillow is easily installable in a virtualenv. If you have problems installing pillow, use a more generic FileField instead. """ - file = models.ImageField(upload_to="pictures") - slug = models.SlugField(max_length=50, blank=True) + file = models.FileField() + slug = models.SlugField(max_length=50, blank=True) + token = models.ForeignKey(SingleUseToken, on_delete=models.CASCADE) def __unicode__(self): return self.file.name @@ -21,9 +33,9 @@ def get_absolute_url(self): def save(self, *args, **kwargs): self.slug = self.file.name - super(Picture, self).save(*args, **kwargs) + super(File, self).save(*args, **kwargs) def delete(self, *args, **kwargs): """delete -- Remove to leave file.""" self.file.delete(False) - super(Picture, self).delete(*args, **kwargs) + super(File, self).delete(*args, **kwargs) diff --git a/fileupload/serialize.py b/fileupload/serialize.py index 4494e79..c69b043 100644 --- a/fileupload/serialize.py +++ b/fileupload/serialize.py @@ -18,9 +18,9 @@ def order_name(name): def serialize(instance, file_attr='file'): - """serialize -- Serialize a Picture instance into a dict. + """serialize -- Serialize a File instance into a dict. - instance -- Picture instance + instance -- File instance file_attr -- attribute name that contains the FileField or ImageField """ @@ -31,8 +31,6 @@ def serialize(instance, file_attr='file'): 'type': mimetypes.guess_type(obj.path)[0] or 'image/png', 'thumbnailUrl': obj.url, 'size': obj.size, - 'deleteUrl': reverse('upload-delete', args=[instance.pk]), + 'deleteUrl': reverse('upload-delete', args=[instance.token.token,instance.pk]), 'deleteType': 'DELETE', } - - diff --git a/fileupload/static/css/style.css b/fileupload/static/css/style.css index 6f1a7f2..c6697bd 100644 --- a/fileupload/static/css/style.css +++ b/fileupload/static/css/style.css @@ -10,10 +10,6 @@ * http://www.opensource.org/licenses/MIT */ -body { - padding-top: 60px; -} - .preview img { max-height:50px; -} \ No newline at end of file +} diff --git a/fileupload/static/js/app.js b/fileupload/static/js/app.js index 729eb1a..e3d9839 100644 --- a/fileupload/static/js/app.js +++ b/fileupload/static/js/app.js @@ -11,14 +11,10 @@ /*jslint nomen: true, regexp: true */ /*global window, angular */ - -(function () { +function createControllers(url, urlview) { 'use strict'; - - var isOnGitHub = window.location.hostname === 'blueimp.github.io', - url = '/upload/angular/', - urlview = '/upload/view/'; + var demo_settings = false angular.module('demo', [ 'blueimp.fileupload' @@ -32,7 +28,7 @@ '/cors/result.html?%s' ); - if (isOnGitHub) { + if (demo_settings) { // Demo settings: angular.extend(fileUploadProvider.defaults, { // Enable image resizing, except for Android and Opera, @@ -53,7 +49,7 @@ $scope.options = { url: url }; - if (!isOnGitHub) { + if (!demo_settings) { $scope.loadingFiles = true; $http.get(urlview) .then( @@ -102,5 +98,4 @@ } } ]); - -}()); +}; diff --git a/fileupload/templates/fileupload/file_angular_form.html b/fileupload/templates/fileupload/file_angular_form.html new file mode 100644 index 0000000..d39cf37 --- /dev/null +++ b/fileupload/templates/fileupload/file_angular_form.html @@ -0,0 +1,176 @@ +{% load staticfiles %} + + + +
+ + + +--File Upload widget with multiple file selection, drag&drop support, progress bars, validation and preview images, audio and video for AngularJS.
-
- Supports cross-domain, chunked and resumable file uploads and client-side image resizing.