diff --git a/README.md b/README.md
index 8f185a9..a5596da 100644
--- a/README.md
+++ b/README.md
@@ -1,23 +1,8 @@
-[jQuery-File-Upload](http://aquantum-demo.appspot.com/file-upload) is developed by Sebastian Tschan, with the source available on [github](https://github.com/blueimp/jQuery-File-Upload). Example code is [ported to Django](https://github.com/sigurdga/django-jquery-file-upload) by Sigurd Gartmann ([sigurdga on github](https://github.com/sigurdga/)).
+Disclaimer
+==========
-Introduction
-============
-
-This is a small example on how to setup Sebastian Tschan's jQuery File Upload in Django. He has a working demo on his [webpage](http://aquantum-demo.appspot.com/file-upload) and a [github repository](https://github.com/blueimp/jQuery-File-Upload) with an example on how to do it in PHP.
-
-Here, you'll find a minimal Django project with a minimal app. You can run the example standalone by cloning the repository, running the migrations and starting the server.
-
-I want to give a thank to [Sebastian Tschan](https://github.com/blueimp), the original author, [Etay Cohen-Solal](https://github.com/et-cs), for the latest major update, and [Jørgen Bergquist](https://github.com/bergquis) for helping me over the first hurdles.
-
-Features
-========
+This project is a fork
-* Drag and drop files
-* Select multiple files
-* Cancel upload
-* Delete uploaded file (from database only)
-* No flash (or other browser plugins) needed
-* … more at the [upstream's features page](http://aquantum-demo.appspot.com/file-upload#features)
Requirements
============
@@ -37,6 +22,25 @@ Installation
* python manage.py runserver
* go to localhost:8000/upload/new/ and upload some files
+Developing with docker
+======================
+ $ docker run -ti --name uploaderdevel -p 8000:8000 -v /workdir/django_uploader:/devel python:2.7.18 bash
+ $ pip install -r requirements.txt
+ $ export DJANGO_SETTINGS_MODULE=settings_dev
+ $ python manage.py runserver 0.0.0.0:8000
+
+Database migrations
+===================
+
+From existing DB
+ $ python manage.py schemamigration fileupload --initial
+ $ python manage.py migrate --fake
+
+
+Generate migration and apply
+ $ python manage.py schemamigration fileupload --auto
+ $ python manage.py migrate fileupload
+
License
=======
MIT, as the original project. See LICENSE.txt.
diff --git a/core/wsgi.py b/core/wsgi.py
new file mode 100644
index 0000000..5151301
--- /dev/null
+++ b/core/wsgi.py
@@ -0,0 +1,58 @@
+"""
+WSGI config for finto project.
+
+This module contains the WSGI application used by Django's development server
+and any production WSGI deployments. It should expose a module-level variable
+named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover
+this application via the ``WSGI_APPLICATION`` setting.
+
+Usually you will have the standard Django WSGI application here, but it also
+might make sense to replace the whole Django WSGI application with a custom one
+that later delegates to the Django one. For example, you could introduce WSGI
+middleware here, or combine a Django application with an application of another
+framework.
+
+"""
+import os
+import sys
+import site
+
+ALLDIRS = ['/var/www/djuploader/lib/python2.7/site-packages']
+
+path = '/var/www/djuploader/dj-src'
+if path not in sys.path:
+ sys.path.append(path)
+
+# Remember original sys.path.
+prev_sys_path = list(sys.path)
+
+# Add each new site-packages directory.
+for directory in ALLDIRS:
+ site.addsitedir(directory)
+
+# Reorder sys.path so new directories at the front.
+new_sys_path = []
+for item in list(sys.path):
+ if item not in prev_sys_path:
+ new_sys_path.append(item)
+ sys.path.remove(item)
+sys.path[:0] = new_sys_path
+
+activate_this = '/var/www/djuploader/bin/activate_this.py'
+execfile(activate_this, dict(__file__=activate_this))
+
+# We defer to a DJANGO_SETTINGS_MODULE already in the environment. This breaks
+# if running multiple sites in the same mod_wsgi process. To fix this, use
+# mod_wsgi daemon mode with each site in its own daemon process, or use
+# os.environ["DJANGO_SETTINGS_MODULE"] = "finto.settings"
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings")
+
+# This application object is used by any WSGI server configured to use this
+# file. This includes Django's development server, if the WSGI_APPLICATION
+# setting points here.
+from django.core.wsgi import get_wsgi_application
+application = get_wsgi_application()
+
+# Apply WSGI middleware here.
+# from helloworld.wsgi import HelloWorldApplication
+# application = HelloWorldApplication(application)
diff --git a/deploy/apache/apache.conf b/deploy/apache/apache.conf
new file mode 100644
index 0000000..0612f85
--- /dev/null
+++ b/deploy/apache/apache.conf
@@ -0,0 +1,52 @@
+# WSGISocketPrefix
+WSGISocketPrefix /var/run/wsgi
+WSGIPythonPath /path_to_app:/path_to_virtualenv/lib/python2.7/site-packages
+
+###################
+# web uploads
+#
+
+# config from http://wiki.apache.org/httpd/NameBasedSSLVHosts
+ SSLEngine on
+ SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP
+
+ SSLCertificateFile /etc/ssl/certs/cert.com.crt
+ SSLCertificateKeyFile /etc/ssl/certs/cert.com.key
+ SSLCertificateChainFile /etc/ssl/certs/StandardSSLCA.pem
+ SSLVerifyClient None
+
+ ServerName "foo"
+ ServerAdmin "webmaster@foo"
+
+ CustomLog "/var/log/httpd/upload-access.log" combined
+ ErrorLog "/var/log/httpd/upload-error.log"
+
+ # Django file uploader
+ ###################################################
+ Alias /media/ /var/media-storage/
+ AliasMatch ^/([^/]*\.css) /path_to_app/static/css/$1
+ Alias /static/ /path_to_app/static/
+
+
+ Require all granted
+
+
+
+ Require all denied
+
+
+ WSGIScriptAlias /secureupload /path_to_app/core/wsgi.py
+
+
+ SSLRequireSSL
+
+
+ Require all granted
+
+
+
+
+# END WEBUPLOADS
+#################
+
+# /* vim: set expandtab tabstop=4 shiftwidth=4: */
diff --git a/deploy/selinux/djuploader2.0.te b/deploy/selinux/djuploader2.0.te
new file mode 100644
index 0000000..9e96269
--- /dev/null
+++ b/deploy/selinux/djuploader2.0.te
@@ -0,0 +1,12 @@
+
+module djuploader 1.0;
+
+require {
+ type httpd_t;
+ type var_t;
+ class file { getattr unlink };
+}
+
+#============= httpd_t ==============
+allow httpd_t var_t:file unlink;
+allow httpd_t var_t:file getattr;
diff --git a/fileupload/admin.py b/fileupload/admin.py
index faa5cdc..c924e8d 100644
--- a/fileupload/admin.py
+++ b/fileupload/admin.py
@@ -1,4 +1,98 @@
-from fileupload.models import Picture
+from fileupload.models import File
from django.contrib import admin
+from django.http import HttpResponse
+import tarfile
+import shutil
+from django.contrib import messages
+from django.conf import settings
+import os.path, time
+import datetime as dt
-admin.site.register(Picture)
\ No newline at end of file
+def validate_size(files, maxsize):
+ total_size = 0
+ if len(files) > 1:
+ for file in files:
+ total_size += file.file.size
+
+ return total_size <= maxsize
+ return True
+
+def make_download(modeladmin, request, queryset):
+
+ try:
+ response = HttpResponse(mimetype='application/x-gzip')
+ response['Content-Disposition'] = 'attachment; filename=MD_secure_upload_download.tar.gz'
+ tarred = tarfile.open(fileobj=response, mode='w:gz')
+
+
+ if not validate_size(queryset,1000000000):
+ messages.warning(request, "Download group is too big, unselect some files or select just 1, max size of multple download: 1.0 GB")
+
+ else:
+
+ for file in queryset:
+ tarred.add(settings.MEDIA_ROOT+file.file.name, arcname=file.file.name )
+ tarred.close()
+
+ return response
+
+ except tarfile.TarError:
+ messages.error(request, "Error while creating the TAR archive, contact the webmaster.")
+ except :
+ messages.error(request, "There was an error, please contact the webmaster")
+
+
+make_download.short_description = "Download selected files"
+
+
+def make_archive(modeladmin, request, queryset):
+
+ try:
+
+ for file in queryset:
+ archive_dir = os.path.join(settings.ARCHIVE_ROOT,file.username)
+ if not os.path.exists(archive_dir):
+ os.makedirs(archive_dir)
+
+ shutil.copyfile(settings.MEDIA_ROOT+file.file.name, os.path.join(archive_dir,file.slug))
+
+ file.delete()
+
+ messages.info(request, file.slug + " Archived Successfully")
+
+ except shutil.Error:
+ messages.error(request, "File Copy error, please contact the webmaster")
+ except :
+ messages.error(request, "There was an error, please contact the webmaster")
+
+make_archive.short_description = "Archive selected files"
+
+
+def file_size(obj):
+ try:
+ if obj.file.size < 1000000:
+ return ("%s bytes" % (obj.file.size))
+ return ("%s MBs" % (obj.file.size/1000000))
+ except OSError:
+ return ("File Not found")
+
+file_size.short_description = 'Size'
+
+# deprecated
+def last_modified(obj):
+ date_text = "File Not Found"
+ filepath = settings.MEDIA_ROOT+obj.file.name
+ if os.path.exists(filepath):
+ date_text = "%s" % dt.datetime.fromtimestamp(os.path.getmtime(filepath))
+
+ return date_text
+
+class FileAdmin(admin.ModelAdmin):
+ list_display = ('slug','username', 'date', file_size)
+ list_filter = ('username',)
+ search_fields = ['slug', 'username', 'date']
+ ordering = ('username','slug', 'date')
+ actions = [make_download,make_archive]
+
+
+admin.site.register(File,FileAdmin)
diff --git a/fileupload/migrations/0001_initial.py b/fileupload/migrations/0001_initial.py
new file mode 100644
index 0000000..3d87f52
--- /dev/null
+++ b/fileupload/migrations/0001_initial.py
@@ -0,0 +1,36 @@
+# -*- coding: utf-8 -*-
+from south.utils import datetime_utils as datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+ # Adding model 'File'
+ db.create_table(u'fileupload_file', (
+ (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('file', self.gf('django.db.models.fields.files.FileField')(max_length=100)),
+ ('slug', self.gf('django.db.models.fields.SlugField')(max_length=50, blank=True)),
+ ('username', self.gf('django.db.models.fields.CharField')(max_length=50)),
+ ))
+ db.send_create_signal(u'fileupload', ['File'])
+
+
+ def backwards(self, orm):
+ # Deleting model 'File'
+ db.delete_table(u'fileupload_file')
+
+
+ models = {
+ u'fileupload.file': {
+ 'Meta': {'object_name': 'File'},
+ 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ }
+ }
+
+ complete_apps = ['fileupload']
\ No newline at end of file
diff --git a/fileupload/migrations/0002_auto__add_field_file_date.py b/fileupload/migrations/0002_auto__add_field_file_date.py
new file mode 100644
index 0000000..45648fa
--- /dev/null
+++ b/fileupload/migrations/0002_auto__add_field_file_date.py
@@ -0,0 +1,33 @@
+# -*- coding: utf-8 -*-
+from south.utils import datetime_utils as datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+ # Adding field 'File.date'
+ db.add_column(u'fileupload_file', 'date',
+ self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now, blank=True),
+ keep_default=False)
+
+
+ def backwards(self, orm):
+ # Deleting field 'File.date'
+ db.delete_column(u'fileupload_file', 'date')
+
+
+ models = {
+ u'fileupload.file': {
+ 'Meta': {'object_name': 'File'},
+ 'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'blank': 'True'}),
+ 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ }
+ }
+
+ complete_apps = ['fileupload']
\ No newline at end of file
diff --git a/fileupload/migrations/0003_auto__chg_field_file_date.py b/fileupload/migrations/0003_auto__chg_field_file_date.py
new file mode 100644
index 0000000..24d9c92
--- /dev/null
+++ b/fileupload/migrations/0003_auto__chg_field_file_date.py
@@ -0,0 +1,31 @@
+# -*- coding: utf-8 -*-
+from south.utils import datetime_utils as datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+
+ # Changing field 'File.date'
+ db.alter_column(u'fileupload_file', 'date', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True))
+
+ def backwards(self, orm):
+
+ # Changing field 'File.date'
+ db.alter_column(u'fileupload_file', 'date', self.gf('django.db.models.fields.DateTimeField')())
+
+ models = {
+ u'fileupload.file': {
+ 'Meta': {'object_name': 'File'},
+ 'date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ }
+ }
+
+ complete_apps = ['fileupload']
\ No newline at end of file
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..aff009f 100644
--- a/fileupload/models.py
+++ b/fileupload/models.py
@@ -1,16 +1,20 @@
# encoding: utf-8
+from datetime import datetime
from django.db import models
+# Receive the pre_delete signal and delete the file associated with the model instance.
+from django.db.models.signals import post_delete
+from django.dispatch.dispatcher import receiver
-class Picture(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)
+def upload_dir_path(instance, filename):
+ return 'uploaded_files/%s/%s' % (instance.username, filename)
+
+class File(models.Model):
+ file = models.FileField(upload_to=upload_dir_path)
+ date = models.DateTimeField(auto_now_add=True, blank=True)
+ slug = models.SlugField(max_length=50, blank=True, verbose_name="file name")
+ username = models.CharField(max_length=50)
def __unicode__(self):
return self.file.name
@@ -21,9 +25,15 @@ 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)
+
+ # use post_delete signal instead
+ #def delete(self, *args, **kwargs):
+ # """delete -- Remove to leave file."""
+ # self.file.delete(False)
+ # super(File, self).delete(*args, **kwargs)
- def delete(self, *args, **kwargs):
- """delete -- Remove to leave file."""
- self.file.delete(False)
- super(Picture, self).delete(*args, **kwargs)
+@receiver(post_delete, sender=File)
+def File_delete(sender, instance, **kwargs):
+ # Pass false so FileField doesn't save the model.
+ instance.file.delete(False)
diff --git a/fileupload/serialize.py b/fileupload/serialize.py
index 4494e79..868a17d 100644
--- a/fileupload/serialize.py
+++ b/fileupload/serialize.py
@@ -12,15 +12,15 @@ def order_name(name):
"""
name = re.sub(r'^.*/', '', name)
- if len(name) <= 20:
+ if len(name) <= 37:
return name
- return name[:10] + "..." + name[-7:]
+ return name[:37] + "..." + name[-7:]
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
"""
@@ -28,7 +28,8 @@ def serialize(instance, file_attr='file'):
return {
'url': obj.url,
'name': order_name(obj.name),
- 'type': mimetypes.guess_type(obj.path)[0] or 'image/png',
+ #'type': mimetypes.guess_type(obj.path)[0] or 'image/png',
+ 'type': mimetypes.guess_type(obj.path)[0],
'thumbnailUrl': obj.url,
'size': obj.size,
'deleteUrl': reverse('upload-delete', args=[instance.pk]),
diff --git a/fileupload/static/css/demo.css b/fileupload/static/css/demo.css
index 841f80d..d5d5b0e 100644
--- a/fileupload/static/css/demo.css
+++ b/fileupload/static/css/demo.css
@@ -15,10 +15,11 @@ body {
margin: 0 auto;
padding: 1em;
font-family: 'Lucida Grande', 'Lucida Sans Unicode', Arial, sans-serif;
- font-size: 1em;
- line-height: 1.4em;
- background: #222;
- color: #fff;
+ font-size: 10pt;
+ font-weight: bold;
+ line-height: 0em;
+ background: #E2E2E2;
+ color: #333333;
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
}
@@ -40,9 +41,25 @@ blockquote {
}
table {
width: 100%;
- margin: 10px 0;
+ margin: 10px 10;
}
+
+table td
+{
+ padding-right: 5px;
+}
+
+.mdtitle h2{
+ font-size: 17px;
+}
+
+.mdtitle table{
+ padding: 2px;
+}
+
+
+
.fileupload-progress {
margin: 10px 0;
}
diff --git a/fileupload/static/css/jquery.fileupload-ui.css b/fileupload/static/css/jquery.fileupload-ui.css
index f81b34c..760f027 100644
--- a/fileupload/static/css/jquery.fileupload-ui.css
+++ b/fileupload/static/css/jquery.fileupload-ui.css
@@ -35,6 +35,51 @@
background: url(../img/progressbar.gif) !important;
filter: none;
}
+
+
+.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default {
+ background: none repeat scroll 0 0 #005491;
+ border: 1px solid #515091;
+ color: #EEEEEE;
+ font-weight: bold;
+ margin: 0px;
+}
+
+.ui-widget-content {
+ border: 1px solid #555555;
+ height: 14px;
+ margin-bottom: 10px;
+ width: 80%;
+ background: #000000 url(../img/progressbar.gif) 50% 50% repeat;
+ color: #ffffff;
+}
+
+.ui-widget-header {
+border: 1px solid #798E9B;
+/*background: #388532 url(images/ui-bg_highlight-soft_44_444444_1x100.png) 50% 50% repeat-x;*/
+background: #005491 url(../img/ui-bg_highlight-soft_44_444444_1x100.png) 50% 50% repeat-x;
+color: #ffffff;
+font-weight: bold;
+}
+
+.ui-widget {
+ font-size: 0.92em;
+}
+
+.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br {
+ border-bottom-right-radius: 6px;
+}
+.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl {
+ border-bottom-left-radius: 6px;
+}
+
+.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr {
+ border-top-right-radius: 6px;
+}
+.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl {
+ border-top-left-radius: 6px;
+}
+
.fileupload-loading {
float: right;
width: 32px;
diff --git a/fileupload/static/img/MD_logo.png b/fileupload/static/img/MD_logo.png
new file mode 100644
index 0000000..47b3350
Binary files /dev/null and b/fileupload/static/img/MD_logo.png differ
diff --git a/fileupload/static/img/ui-bg_highlight-soft_44_444444_1x100.png b/fileupload/static/img/ui-bg_highlight-soft_44_444444_1x100.png
new file mode 100644
index 0000000..32733d6
Binary files /dev/null and b/fileupload/static/img/ui-bg_highlight-soft_44_444444_1x100.png differ
diff --git a/fileupload/static/img/ui-bg_highlight-soft_44_444444_1x100.png.orig b/fileupload/static/img/ui-bg_highlight-soft_44_444444_1x100.png.orig
new file mode 100644
index 0000000..a4e5b22
Binary files /dev/null and b/fileupload/static/img/ui-bg_highlight-soft_44_444444_1x100.png.orig differ
diff --git a/fileupload/static/js/app.js b/fileupload/static/js/app.js
index 729eb1a..404b13d 100644
--- a/fileupload/static/js/app.js
+++ b/fileupload/static/js/app.js
@@ -40,7 +40,7 @@
// send Blob objects via XHR requests:
disableImageResize: /Android(?!.*Chrome)|Opera/
.test(window.navigator.userAgent),
- maxFileSize: 5000000,
+ maxFileSize: 100000,
acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i
});
}
diff --git a/fileupload/static/js/jquery.fileupload-validate.js b/fileupload/static/js/jquery.fileupload-validate.js
index ee1c2f2..de37447 100644
--- a/fileupload/static/js/jquery.fileupload-validate.js
+++ b/fileupload/static/js/jquery.fileupload-validate.js
@@ -71,7 +71,7 @@
maxNumberOfFiles: 'Maximum number of files exceeded',
acceptFileTypes: 'File type not allowed',
maxFileSize: 'File is too large',
- minFileSize: 'File is too small'
+ minFileSize: 'File is too small, min allowed size is 0.1MB.'
}
},
diff --git a/fileupload/static/js/locale.js b/fileupload/static/js/locale.js
index ea64b0a..3375080 100644
--- a/fileupload/static/js/locale.js
+++ b/fileupload/static/js/locale.js
@@ -15,7 +15,7 @@ window.locale = {
"fileupload": {
"errors": {
"maxFileSize": "File is too big",
- "minFileSize": "File is too small",
+ "minFileSize": "File is too small, minumum size is 5MB.",
"acceptFileTypes": "Filetype not allowed",
"maxNumberOfFiles": "Max number of files exceeded",
"uploadedBytes": "Uploaded bytes exceed file size",
diff --git a/fileupload/static/js/main.js b/fileupload/static/js/main.js
index 1850909..3a2add2 100644
--- a/fileupload/static/js/main.js
+++ b/fileupload/static/js/main.js
@@ -17,6 +17,8 @@ $(function () {
// Initialize the jQuery File Upload widget:
$('#fileupload').fileupload({
+
+ minFileSize: 100000,
// Uncomment the following to send cross-domain cookies:
//xhrFields: {withCredentials: true},
//url: 'server/php/'
@@ -32,46 +34,20 @@ $(function () {
)
);
- if (window.location.hostname === 'blueimp.github.io') {
- // Demo settings:
- $('#fileupload').fileupload('option', {
- url: '//jquery-file-upload.appspot.com/',
- // Enable image resizing, except for Android and Opera,
- // which actually support image resizing, but fail to
- // send Blob objects via XHR requests:
- disableImageResize: /Android(?!.*Chrome)|Opera/
- .test(window.navigator.userAgent),
- maxFileSize: 5000000,
- acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i
- });
- // Upload server status check for browsers with CORS support:
- if ($.support.cors) {
- $.ajax({
- url: '//jquery-file-upload.appspot.com/',
- type: 'HEAD'
- }).fail(function () {
- $('
')
- .text('Upload server currently unavailable - ' +
- new Date())
- .appendTo('#fileupload');
- });
- }
- } else {
- // Load existing files:
- $('#fileupload').addClass('fileupload-processing');
- $.ajax({
- // Uncomment the following to send cross-domain cookies:
- //xhrFields: {withCredentials: true},
- //url: $('#fileupload').fileupload('option', 'url'),
- url: '/upload/view/',
- dataType: 'json',
- context: $('#fileupload')[0]
- }).always(function () {
- $(this).removeClass('fileupload-processing');
- }).done(function (result) {
- $(this).fileupload('option', 'done')
- .call(this, null, {result: result});
- });
- }
+ // Load existing files:
+ $('#fileupload').addClass('fileupload-processing');
+ $.ajax({
+ // Uncomment the following to send cross-domain cookies:
+ //xhrFields: {withCredentials: true},
+ //url: $('#fileupload').fileupload('option', 'url'),
+ url: 'https://upload.moldiscovery.com/secureupload/upload/view/',
+ dataType: 'json',
+ context: $('#fileupload')[0]
+ }).always(function () {
+ $(this).removeClass('fileupload-processing');
+ }).done(function (result) {
+ $(this).fileupload('option', 'done')
+ .call(this, null, {result: result});
+ });
});
diff --git a/fileupload/templates/fileupload/file_jquery_form.html b/fileupload/templates/fileupload/file_jquery_form.html
new file mode 100644
index 0000000..e1d5c68
--- /dev/null
+++ b/fileupload/templates/fileupload/file_jquery_form.html
@@ -0,0 +1,269 @@
+
+
+
+
+
+
+
+Molecular Discovery Secure File Upload
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{% block contents %}
+{% if user.is_authenticated %}
+
+
+
+ Molecular Discovery Secure File Upload.
+
MAX aggregated files upload size: 4 GB
+ TIP: compress or chunck big files before uploading
+
+
+
+
+
+
+ You are logged in as: {{ user }}, Logout
+
+
+
+
+
+
+
+{% else %}
+
+
Molecular Discovery Secure Upload Login.
+
+ Please use the login credential that our staff provided you:
+
+
+
+{% endif %}
+{% endblock %}
+
+
+
+{% verbatim %}
+
+
+{% endverbatim %}
+
+{% if perms.fileupload %}
+
+{% verbatim %}
+
+
+{% endverbatim %}
+
+{% else %}
+
+{% verbatim %}
+
+
+{% endverbatim %}
+
+
+{% endif %}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/fileupload/templates/fileupload/picture_angular_form.html b/fileupload/templates/fileupload/picture_angular_form.html
deleted file mode 100644
index a5ac9c0..0000000
--- a/fileupload/templates/fileupload/picture_angular_form.html
+++ /dev/null
@@ -1,207 +0,0 @@
-
-
-
-
-
-
-
-jQuery File Upload Demo - AngularJS version
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Django jQuery File Upload Demo
-
AngularJS version
-
-
-
- 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.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/fileupload/templates/fileupload/picture_basic_form.html b/fileupload/templates/fileupload/picture_basic_form.html
deleted file mode 100644
index 6bd17a4..0000000
--- a/fileupload/templates/fileupload/picture_basic_form.html
+++ /dev/null
@@ -1,130 +0,0 @@
-
-
-
-
-
-
-Django jQuery File Upload Demo - Basic version
-
-
-
-
-
-
-
-
-
-
-
-
-
Django jQuery File Upload Demo
-
Basic version
-
-
-
- File Upload widget with multiple file selection, drag&drop support and progress bar for jQuery.
- Supports cross-domain, chunked and resumable file uploads.
-
-
-
-
-
- Select files...
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/fileupload/templates/fileupload/picture_basicplus_form.html b/fileupload/templates/fileupload/picture_basicplus_form.html
deleted file mode 100644
index eb1cc1c..0000000
--- a/fileupload/templates/fileupload/picture_basicplus_form.html
+++ /dev/null
@@ -1,221 +0,0 @@
-
-
-
-
-
-
-jQuery File Upload Demo - Basic Plus version
-
-
-
-
-
-
-
-
-
-
-
-
-
Django jQuery File Upload Demo
-
Basic Plus version
-
-
-
- File Upload widget with multiple file selection, drag&drop support, progress bar, validation and preview images, audio and video for jQuery.
- Supports cross-domain, chunked and resumable file uploads and client-side image resizing.
-
-
-
-
-
- Add files...
-
-
-
-
-
-
-
-
-
-
-
-
-
Demo Notes
-
-
-
- The maximum file size for uploads in this demo is 5 MB (default file size is unlimited).
- Only image files (JPG, GIF, PNG ) are allowed in this demo (by default there is no file type restriction).
- You can drag & drop files from your desktop on this webpage (see Browser support ).
- Please refer to the project website and documentation for more information.
- Built with Twitter's Bootstrap CSS framework and Icons from Glyphicons .
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/fileupload/templates/fileupload/picture_form.html b/fileupload/templates/fileupload/picture_form.html
deleted file mode 100644
index a8754bc..0000000
--- a/fileupload/templates/fileupload/picture_form.html
+++ /dev/null
@@ -1,126 +0,0 @@
-{% extends "upload_base.html" %}
-{% load upload_tags %}
-
-{% block content %}
-
-
Django jQuery File Upload Demo
-
Basic Plus UI version
-
-
-
- File Upload widget with multiple file selection, drag&drop support, progress bars, validation and preview images, audio and video for jQuery.
- Supports cross-domain, chunked and resumable file uploads and client-side image resizing.
-
-
-
-
-
-
-
-
-
-{% upload_js %}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-{% endblock %}
\ No newline at end of file
diff --git a/fileupload/templates/fileupload/picture_jquery_form.html b/fileupload/templates/fileupload/picture_jquery_form.html
deleted file mode 100644
index cf0ed04..0000000
--- a/fileupload/templates/fileupload/picture_jquery_form.html
+++ /dev/null
@@ -1,255 +0,0 @@
-
-
-
-
-
-
-
-Django jQuery File Upload Demo - jQuery UI version
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Django jQuery File Upload Demo
-jQuery UI version
-
-
-
- File Upload widget with multiple file selection, drag&drop support, progress bars, validation and preview images, audio and video for jQuery UI.
- Supports cross-domain, chunked and resumable file uploads and client-side image resizing.
-
-
-
-
-Demo Notes
-
- The maximum file size for uploads in this demo is 5 MB (default file size is unlimited).
- Only image files (JPG, GIF, PNG ) are allowed in this demo (by default there is no file type restriction).
- Uploaded files will be deleted automatically after 5 minutes (demo setting).
- You can drag & drop files from your desktop on this webpage (see Browser support ).
- Please refer to the project website and documentation for more information.
- Built with jQuery UI .
-
-
-
-{% verbatim %}
-
-
-
-
-{% endverbatim %}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/fileupload/templates/upload_base.html b/fileupload/templates/upload_base.html
deleted file mode 100644
index e75c3fc..0000000
--- a/fileupload/templates/upload_base.html
+++ /dev/null
@@ -1,52 +0,0 @@
-
-
-
-
-
-
- Django Jquery file upload demo
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-{% block content %}
- No content set
-{% endblock %}
-
-
-
diff --git a/fileupload/urls.py b/fileupload/urls.py
index dbbcbca..963aa68 100644
--- a/fileupload/urls.py
+++ b/fileupload/urls.py
@@ -1,17 +1,16 @@
# encoding: utf-8
from django.conf.urls import patterns, url
+
from fileupload.views import (
- BasicVersionCreateView, BasicPlusVersionCreateView,
- jQueryVersionCreateView, AngularVersionCreateView,
- PictureCreateView, PictureDeleteView, PictureListView,
+ jQueryVersionCreateView,
+ FileCreateView, FileDeleteView, FileListView,
+ login_view, logout_view,
)
urlpatterns = patterns('',
- url(r'^basic/$', BasicVersionCreateView.as_view(), name='upload-basic'),
- url(r'^basic/plus/$', BasicPlusVersionCreateView.as_view(), name='upload-basic-plus'),
- url(r'^new/$', PictureCreateView.as_view(), name='upload-new'),
- url(r'^angular/$', AngularVersionCreateView.as_view(), name='upload-angular'),
- url(r'^jquery-ui/$', jQueryVersionCreateView.as_view(), name='upload-jquery'),
- url(r'^delete/(?P\d+)$', PictureDeleteView.as_view(), name='upload-delete'),
- url(r'^view/$', PictureListView.as_view(), name='upload-view'),
+ url(r'^login/$', login_view, name='login'),
+ url(r'^logout/$', logout_view, name='logout'),
+ url(r'^home/$', jQueryVersionCreateView.as_view(), name='upload-jquery'),
+ url(r'^delete/(?P\d+)$', FileDeleteView.as_view(), name='upload-delete'),
+ url(r'^view/$', FileListView.as_view(), name='upload-view'),
)
diff --git a/fileupload/views.py b/fileupload/views.py
index 98b339c..0be5568 100644
--- a/fileupload/views.py
+++ b/fileupload/views.py
@@ -3,46 +3,87 @@
from django.http import HttpResponse
from django.views.generic import CreateView, DeleteView, ListView
-from .models import Picture
+from .models import File
from .response import JSONResponse, response_mimetype
from .serialize import serialize
-
-
-class PictureCreateView(CreateView):
- model = Picture
+from django.contrib.auth import authenticate, login
+from django.contrib.auth import logout
+from django.shortcuts import redirect
+import smtplib
+
+def send_email(response,user):
+
+ FROMADDR = "uploads@www2.moldiscovery.com"
+ LOGIN = FROMADDR
+ #PASSWORD = ""
+ TOADDRS = ["fabrizio@moldiscovery.com"]
+ SUBJECT = "Files uploaded"
+ msg_content = "User: %s \r\n" % user
+
+ for file in response['files']:
+ msg_content += "File Uploaded: "+ file['name'] + '\r\n'
+ msg_content += "File Size: "+ str(file['size']) + ' bytes\r\n'
+ msg_content += "Download: https://www2.moldiscovery.com/secureupload/admin/" + '\r\n\r\n'
+
+ msg = ("From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n"
+ % (FROMADDR, ", ".join(TOADDRS), SUBJECT) )
+ msg += msg_content+"\r\n"
+
+ server = smtplib.SMTP('localhost', 25)
+ #server.set_debuglevel(1)
+ server.ehlo("www2.moldiscovery.com")
+ #server.starttls()
+ #server.login(LOGIN, PASSWORD)
+ server.sendmail(FROMADDR, TOADDRS, msg)
+ server.quit()
+
+
+def logout_view(request):
+ logout(request)
+ return redirect('home')
+
+def login_view(request):
+
+ username = request.POST['username']
+ password = request.POST['password']
+ user = authenticate(username=username, password=password)
+ if user is not None:
+ if user.is_active:
+ login(request, user)
+
+ return redirect('home')
+
+class FileCreateView(CreateView):
+ model = File
def form_valid(self, form):
+ if not self.request.user.is_authenticated():
+ return redirect('home')
+
self.object = form.save()
files = [serialize(self.object)]
data = {'files': files}
response = JSONResponse(data, mimetype=response_mimetype(self.request))
response['Content-Disposition'] = 'inline; filename=files.json'
+ #send_email(data, self.request.user.username)
return response
def form_invalid(self, form):
data = json.dumps(form.errors)
return HttpResponse(content=data, status=400, content_type='application/json')
-class BasicVersionCreateView(PictureCreateView):
- template_name_suffix = '_basic_form'
-
-
-class BasicPlusVersionCreateView(PictureCreateView):
- template_name_suffix = '_basicplus_form'
-
-class AngularVersionCreateView(PictureCreateView):
- template_name_suffix = '_angular_form'
-
-
-class jQueryVersionCreateView(PictureCreateView):
+class jQueryVersionCreateView(FileCreateView):
template_name_suffix = '_jquery_form'
-class PictureDeleteView(DeleteView):
- model = Picture
+class FileDeleteView(DeleteView):
+ model = File
def delete(self, request, *args, **kwargs):
+ if not self.request.user.is_authenticated():
+ return redirect('home')
+
self.object = self.get_object()
self.object.delete()
response = JSONResponse(True, mimetype=response_mimetype(request))
@@ -50,10 +91,17 @@ def delete(self, request, *args, **kwargs):
return response
-class PictureListView(ListView):
- model = Picture
+class FileListView(ListView):
+ model = File
+
+ def get_queryset(self):
+ return File.objects.filter(username=self.request.user)
def render_to_response(self, context, **response_kwargs):
+
+ if not self.request.user.is_authenticated():
+ return redirect('home')
+
files = [ serialize(p) for p in self.get_queryset() ]
data = {'files': files}
response = JSONResponse(data, mimetype=response_mimetype(self.request))
diff --git a/manage.py b/manage.py
index 3e4eedc..f9726f9 100755
--- a/manage.py
+++ b/manage.py
@@ -1,14 +1,10 @@
#!/usr/bin/env python
-from django.core.management import execute_manager
-import imp
-try:
- imp.find_module('settings') # Assumed to be in the same directory.
-except ImportError:
- import sys
- sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n" % __file__)
- sys.exit(1)
-
-import settings
+import os
+import sys
if __name__ == "__main__":
- execute_manager(settings)
+ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings")
+
+ from django.core.management import execute_from_command_line
+
+ execute_from_command_line(sys.argv)
diff --git a/requirements.txt b/requirements.txt
index 23cb63a..8790390 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,2 +1,3 @@
-django<1.6
-pillow
+django==1.5.12
+pillow==6.2.2
+South==1.0.2
diff --git a/settings.py b/settings.py
index 68744b1..7b0832d 100644
--- a/settings.py
+++ b/settings.py
@@ -1,12 +1,16 @@
import os
-DEBUG = True
+DEBUG = False
TEMPLATE_DEBUG = DEBUG
+ALLOWED_HOSTS = ['upload.moldiscovery.com','www2.moldiscovery.com','localhost','127.0.0.1','ajax.googleapis.com']
+
SITE_ROOT = os.path.dirname(os.path.realpath(__file__))
+SERVER_EMAIL = 'admin@www2.moldiscovery.com'
+
ADMINS = (
- # ('Your Name', 'your_email@example.com'),
+ ('SysAdmin', 'fabrizio@moldiscovery.com'),
)
MANAGERS = ADMINS
@@ -29,7 +33,7 @@
# 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'
+TIME_ZONE = 'Europe/Rome'
# Language code for this installation. All choices can be found here:
# http://www.i18nguy.com/unicode/language-identifiers.html
@@ -47,13 +51,16 @@
# Absolute filesystem path to the directory that will hold user-uploaded files.
# Example: "/home/media/media.lawrence.com/media/"
-MEDIA_ROOT = os.path.abspath(os.path.dirname(__file__)) + '/media/'
+#MEDIA_ROOT = os.path.abspath(os.path.dirname(__file__)) + '/media/'
+MEDIA_ROOT = '/var/media-storage/'
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash.
# Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
MEDIA_URL = '/media/'
+ARCHIVE_ROOT = os.path.join(MEDIA_ROOT,'archived')
+
# Absolute path to the directory static files should be collected to.
# Don't put anything in this directory yourself; store your static files
# in apps' "static/" subdirectories and in STATICFILES_DIRS.
@@ -102,7 +109,7 @@
'django.contrib.messages.middleware.MessageMiddleware',
)
-ROOT_URLCONF = 'django-jquery-file-upload.urls'
+ROOT_URLCONF = 'urls'
TEMPLATE_DIRS = (
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
@@ -133,11 +140,17 @@
'version': 1,
'disable_existing_loggers': False,
'handlers': {
- 'mail_admins': {
- 'level': 'ERROR',
- 'class': 'django.utils.log.AdminEmailHandler'
+ 'mail_admins': {
+ 'level': 'ERROR',
+ 'filters': ['require_debug_false'],
+ 'class': 'django.utils.log.AdminEmailHandler'
}
},
+ 'filters': {
+ 'require_debug_false': {
+ '()': 'django.utils.log.RequireDebugFalse'
+ }
+ },
'loggers': {
'django.request': {
'handlers': ['mail_admins'],
diff --git a/settings_dev.py b/settings_dev.py
new file mode 100644
index 0000000..4806e13
--- /dev/null
+++ b/settings_dev.py
@@ -0,0 +1,160 @@
+import os
+
+DEBUG = True
+TEMPLATE_DEBUG = DEBUG
+
+# uncomment this on production server and DEBUG=False
+#ALLOWED_HOSTS = ['ml.moldiscovery.com','ajax.googleapis.com']
+
+SITE_ROOT = os.path.dirname(os.path.realpath(__file__))
+
+ADMINS = (
+ ('Fabrizio Buratta', 'fabrizio@moldiscovery.com'),
+)
+
+MANAGERS = ADMINS
+
+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.
+ }
+}
+
+# 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 = 'Europe/Rome'
+
+# 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
+
+# Absolute filesystem path to the directory that will hold user-uploaded files.
+# Example: "/home/media/media.lawrence.com/media/"
+MEDIA_ROOT = os.path.abspath(os.path.dirname(__file__)) + '/media/'
+
+ARCHIVE_ROOT = os.path.join(MEDIA_ROOT,'archived')
+
+# URL that handles the media served from MEDIA_ROOT. Make sure to use a
+# trailing slash.
+# Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
+MEDIA_URL = '/media/'
+
+# Absolute path to the directory static files should be collected to.
+# Don't put anything in this directory yourself; store your static files
+# in apps' "static/" subdirectories and in STATICFILES_DIRS.
+# Example: "/home/media/media.lawrence.com/static/"
+STATIC_ROOT = os.path.abspath(os.path.dirname(__file__)) + '/static/'
+
+# URL prefix for static files.
+# Example: "http://media.lawrence.com/static/"
+STATIC_URL = '/static/'
+
+# URL prefix for admin static files -- CSS, JavaScript and images.
+# Make sure to use a trailing slash.
+# 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.
+)
+
+# List of finder classes that know how to find static files in
+# various locations.
+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 = (
+ 'django.middleware.common.CommonMiddleware',
+ 'django.contrib.sessions.middleware.SessionMiddleware',
+ 'django.middleware.csrf.CsrfViewMiddleware',
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
+ 'django.contrib.messages.middleware.MessageMiddleware',
+)
+
+ROOT_URLCONF = '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.
+)
+
+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',
+ 'south'
+ # Uncomment the next line to enable admin documentation:
+ # 'django.contrib.admindocs',
+)
+
+# A sample logging configuration. The only tangible logging
+# performed by this configuration is to send an email to
+# the site admins on every HTTP 500 error.
+# See http://docs.djangoproject.com/en/dev/topics/logging for
+# more details on how to customize your logging configuration.
+LOGGING = {
+ 'version': 1,
+ 'disable_existing_loggers': False,
+ 'handlers': {
+ 'mail_admins': {
+ 'level': 'ERROR',
+ 'filters': ['require_debug_false'],
+ 'class': 'django.utils.log.AdminEmailHandler'
+ }
+ },
+ 'filters': {
+ 'require_debug_false': {
+ '()': 'django.utils.log.RequireDebugFalse'
+ }
+ },
+ 'loggers': {
+ 'django.request': {
+ 'handlers': ['mail_admins'],
+ 'level': 'ERROR',
+ 'propagate': True,
+ },
+ }
+}
diff --git a/static/css/jquery.fileupload-ui.css b/static/css/jquery.fileupload-ui.css
new file mode 100644
index 0000000..6d96259
--- /dev/null
+++ b/static/css/jquery.fileupload-ui.css
@@ -0,0 +1,114 @@
+@charset "UTF-8";
+/*
+ * jQuery File Upload UI Plugin CSS 8.8.1
+ * https://github.com/blueimp/jQuery-File-Upload
+ *
+ * Copyright 2010, Sebastian Tschan
+ * https://blueimp.net
+ *
+ * Licensed under the MIT license:
+ * http://www.opensource.org/licenses/MIT
+ */
+
+.fileinput-button {
+ position: relative;
+ overflow: hidden;
+}
+.fileinput-button input {
+ position: absolute;
+ top: 0;
+ right: 0;
+ margin: 0;
+ opacity: 0;
+ filter: alpha(opacity=0);
+ transform: translate(-300px, 0) scale(4);
+ font-size: 23px;
+ direction: ltr;
+ cursor: pointer;
+}
+.fileupload-buttonbar .btn,
+.fileupload-buttonbar .toggle {
+ margin-bottom: 5px;
+}
+.progress-animated .progress-bar,
+.progress-animated .bar {
+ background: url(../img/progressbar.gif) !important;
+ filter: none;
+}
+
+
+.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default {
+ background: none repeat scroll 0 0 #005491;
+ border: 1px solid #515091;
+ color: #EEEEEE;
+ font-weight: bold;
+ margin: 0px;
+}
+
+.ui-widget-content {
+ border: 1px solid #555555;
+ height: 14px;
+ margin-bottom: 10px;
+ width: 80%;
+ background: #000000 url(../img/progressbar.gif) 50% 50% repeat;
+ color: #ffffff;
+}
+
+.ui-widget-header {
+border: 1px solid #798E9B;
+/*background: #388532 url(images/ui-bg_highlight-soft_44_444444_1x100.png) 50% 50% repeat-x;*/
+background: #005491 url(../img/ui-bg_highlight-soft_44_444444_1x100.png) 50% 50% repeat-x;
+color: #ffffff;
+font-weight: bold;
+}
+
+.ui-widget {
+ font-size: 0.92em;
+}
+
+.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br {
+ border-bottom-right-radius: 6px;
+}
+.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl {
+ border-bottom-left-radius: 6px;
+}
+
+.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr {
+ border-top-right-radius: 6px;
+}
+.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl {
+ border-top-left-radius: 6px;
+}
+
+.fileupload-loading {
+ float: right;
+ width: 32px;
+ height: 32px;
+ background: url(../img/loading.gif) center no-repeat;
+ background-size: contain;
+ display: none;
+}
+
+.fileupload-processing .fileupload-loading {
+ display: block;
+}
+.files audio,
+.files video {
+ max-width: 300px;
+}
+
+@media (max-width: 767px) {
+ .fileupload-buttonbar .toggle,
+ .files .toggle,
+ .files .btn span {
+ display: none;
+ }
+ .files .name {
+ width: 80px;
+ word-wrap: break-word;
+ }
+ .files audio,
+ .files video {
+ max-width: 80px;
+ }
+}
diff --git a/urls.py b/urls.py
index 00270ad..e7ae398 100644
--- a/urls.py
+++ b/urls.py
@@ -9,7 +9,7 @@
# Examples:
# url(r'^$', 'upload.views.home', name='home'),
- url(r'^$', lambda x: HttpResponseRedirect('/upload/new/')),
+ url(r'^$', lambda x: HttpResponseRedirect('upload/home'), name='home'),
url(r'^upload/', include('fileupload.urls')),
# Uncomment the admin/doc line below to enable admin documentation:
diff --git a/utils/update_datefield.py b/utils/update_datefield.py
new file mode 100644
index 0000000..b894412
--- /dev/null
+++ b/utils/update_datefield.py
@@ -0,0 +1,41 @@
+# This script can be invoked from python manage.py shell. It's aim is to update the Date Field of the fileupload model
+# with the dates of existing files in the media storage and associated to the model object
+
+import datetime as dt
+import os
+from fileupload.models import File
+from django.conf import settings
+
+
+def sync_slug(allobj):
+ """
+ fill slug field from file name when missing
+ """
+ for obj in allobj:
+ obj.slug = os.path.basename(obj.file.name)
+ obj.save()
+ print("fix missing slug: %s") % obj.slug
+
+db_files = File.objects.all()
+uploads_path = os.path.join(settings.MEDIA_ROOT,'uploaded_files')
+users = set()
+
+sync_slug(db_files)
+
+for f in db_files:
+ users.add(f.username)
+
+for user_dir in users:
+ user_files = os.listdir(os.path.join(uploads_path, user_dir))
+ print(user_dir + " " + str(len(user_files)))
+ for fname in user_files:
+ # only if there are duplicated
+ print("processa "+ " dir: "+user_dir +" name: " + fname)
+ qset = File.objects.filter(username=user_dir, slug=fname)
+ if not qset:
+ print("ERROR: file %s/%s not found") % (user_dir, fname)
+ if len(qset) > 1:
+ print("%s/%s is duplicated") % (user_dir, fname)
+ obj = qset[0]
+ obj.date = dt.datetime.fromtimestamp(os.path.getmtime(os.path.join(uploads_path, user_dir,obj.slug)))
+ obj.save()
\ No newline at end of file