From 7d8f30311679be91424a786f3536ef7e31276e02 Mon Sep 17 00:00:00 2001 From: Piotr Gawron <piotr.gawron@uni.lu> Date: Mon, 11 Dec 2017 16:07:06 +0100 Subject: [PATCH] possibility to upload files that are served by django --- .gitignore | 3 +++ smash/web/models/constants.py | 4 ++++ smash/web/urls.py | 6 ++++++ smash/web/views/__init__.py | 1 + smash/web/views/uploaded_files.py | 25 ++++++++++++++++++++++++ smash/web/widgets/__init__.py | 0 smash/web/widgets/secure_file_widget.py | 26 +++++++++++++++++++++++++ 7 files changed, 65 insertions(+) create mode 100644 smash/web/views/uploaded_files.py create mode 100644 smash/web/widgets/__init__.py create mode 100644 smash/web/widgets/secure_file_widget.py diff --git a/.gitignore b/.gitignore index 7230e12f..a988c9e7 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,9 @@ env/* # Folder with db statics (dev mode) smash/~/ +# files uploaded and hosted by django +smash/uploads/ + # Disable python bytecode *.pyc #vim swap files diff --git a/smash/web/models/constants.py b/smash/web/models/constants.py index 57794ce9..5db58bb9 100644 --- a/smash/web/models/constants.py +++ b/smash/web/models/constants.py @@ -1,6 +1,8 @@ # coding=utf-8 import locale +from django.core.files.storage import FileSystemStorage + BOOL_CHOICES = ((True, 'Yes'), (False, 'No')) SEX_CHOICES_MALE = 'M' SEX_CHOICES_FEMALE = 'F' @@ -90,3 +92,5 @@ VOUCHER_STATUS_CHOICES = ( (VOUCHER_STATUS_USED, 'Used'), (VOUCHER_STATUS_EXPIRED, 'Expired'), ) + +FILE_STORAGE = FileSystemStorage(location='uploads') diff --git a/smash/web/urls.py b/smash/web/urls.py index 1ee0abb3..567ef50b 100644 --- a/smash/web/urls.py +++ b/smash/web/urls.py @@ -206,6 +206,12 @@ urlpatterns = [ url(r'^configuration$', views.configuration_item.configuration_items, name='web.views.configuration'), + #################### + # FILES # + #################### + + url(r'^files/', views.uploaded_files.download, name='web.views.uploaded_files'), + #################### # AUTH # #################### diff --git a/smash/web/views/__init__.py b/smash/web/views/__init__.py index 6f232ada..296d4e9f 100644 --- a/smash/web/views/__init__.py +++ b/smash/web/views/__init__.py @@ -81,3 +81,4 @@ import voucher import voucher_type import voucher_type_price import redcap +import uploaded_files diff --git a/smash/web/views/uploaded_files.py b/smash/web/views/uploaded_files.py new file mode 100644 index 00000000..e20a022a --- /dev/null +++ b/smash/web/views/uploaded_files.py @@ -0,0 +1,25 @@ +# coding=utf-8 +import logging +import ntpath +from wsgiref.util import FileWrapper + +from django.contrib.auth.decorators import login_required +from django.http import HttpResponse + +from web.models.constants import FILE_STORAGE + +logger = logging.getLogger(__name__) + + +def path_to_filename(path): + head, tail = ntpath.split(path) + return tail or ntpath.basename(head) + + +@login_required +def download(request): + if request.GET and request.GET.get('file'): + path = FILE_STORAGE.location + "/" + request.GET.get('file') + response = HttpResponse(FileWrapper(open(path, 'r')), content_type='application/force-download') + response['Content-Disposition'] = 'attachment; filename=%s' % path_to_filename(path) + return response diff --git a/smash/web/widgets/__init__.py b/smash/web/widgets/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/smash/web/widgets/secure_file_widget.py b/smash/web/widgets/secure_file_widget.py new file mode 100644 index 00000000..d26d799f --- /dev/null +++ b/smash/web/widgets/secure_file_widget.py @@ -0,0 +1,26 @@ +import logging + +from django import forms +from django.core.urlresolvers import reverse +from django.utils.safestring import mark_safe +from django.utils.translation import ugettext_lazy as _ + +logger = logging.getLogger(__name__) + + +class SecuredFileWidget(forms.FileInput): + """A FileField Widget that shows secure file link""" + + def __init__(self, attrs=None): + if attrs is None: + attrs = {} + super(SecuredFileWidget, self).__init__(attrs) + + def render(self, name, value, attrs=None): + output = [] + if value and hasattr(value, "url"): + url = reverse('web.views.uploaded_files') + '?file=' + unicode(value) + out = u'<a href="{}">{}</a><br />{} ' + output.append(out.format(url, _(u'Download'), _(u'Change:'))) + output.append(super(SecuredFileWidget, self).render(name, value, attrs)) + return mark_safe(u''.join(output)) -- GitLab