diff --git a/opentech/apply/stream_forms/blocks.py b/opentech/apply/stream_forms/blocks.py index fd7dcdfaf08550809dc5a5451691061ac584fcba..9e3bd04f85e6127ed399c6e1bf58ab6b35a73087 100644 --- a/opentech/apply/stream_forms/blocks.py +++ b/opentech/apply/stream_forms/blocks.py @@ -3,7 +3,10 @@ import bleach from django_bleach.templatetags.bleach_tags import bleach_value from django import forms +from django.conf import settings +from django.core.validators import FileExtensionValidator from django.db.models import BLANK_CHOICE_DASH +from django.forms.widgets import ClearableFileInput from django.utils.dateparse import parse_datetime from django.utils.encoding import force_text from django.utils.text import slugify @@ -327,11 +330,20 @@ class FileFieldBlock(UploadableMediaBlock): You must implement this if you want to reuse it. """ field_class = forms.FileField + widget = ClearableFileInput class Meta: label = _('File field') icon = 'download' + def get_field_kwargs(self, struct_value): + kwargs = super().get_field_kwargs(struct_value) + kwargs['validators'] = [ + FileExtensionValidator(allowed_extensions=settings.FILE_ALLOWED_EXTENSIONS) + ] + kwargs['widget'] = self.get_widget(struct_value)(attrs={'accept': settings.FILE_ACCEPT_ATTR_VALUE}) + return kwargs + class MultiFileFieldBlock(UploadableMediaBlock): field_class = MultiFileField diff --git a/opentech/apply/stream_forms/fields.py b/opentech/apply/stream_forms/fields.py index c45d4f1337f7f482c984b52976827e52c3e92baa..c7a8deed5921ec957558420f721f73f737fdcbef 100644 --- a/opentech/apply/stream_forms/fields.py +++ b/opentech/apply/stream_forms/fields.py @@ -1,3 +1,5 @@ +from django.conf import settings +from django.core.validators import FileExtensionValidator from django.forms import ClearableFileInput, FileField, CheckboxInput @@ -63,7 +65,11 @@ class MultiFileField(FileField): cleared = value['cleared'] if not files and not cleared: return initial - new = [FileField().clean(file, initial) for file in files] + new = [ + FileField(validators=[ + FileExtensionValidator(allowed_extensions=settings.FILE_ALLOWED_EXTENSIONS) + ]).clean(file, initial) for file in files + ] if initial: old = [file for i, file in enumerate(initial) if i not in cleared] @@ -71,3 +77,9 @@ class MultiFileField(FileField): old = [] return old + new + + def widget_attrs(self, widget): + attrs = super().widget_attrs(widget) + if isinstance(widget, MultiFileInput) and 'accept' not in widget.attrs: + attrs.setdefault('accept', settings.FILE_ACCEPT_ATTR_VALUE) + return attrs diff --git a/opentech/settings/base.py b/opentech/settings/base.py index ca17c3ff66873d59355387e1ff0c228ca0b8195e..c3e26f3254393ae8c7160694c60cc355cf78e804 100644 --- a/opentech/settings/base.py +++ b/opentech/settings/base.py @@ -438,6 +438,12 @@ BLEACH_STRIP_TAGS = True BLEACH_STRIP_COMMENTS = True +# File Field settings +FILE_ALLOWED_EXTENSIONS = ['doc', 'docx', 'odp', 'ods', 'odt', 'pdf', 'ppt', 'pptx', 'rtf', 'txt', 'xls', 'xlsx'] + +# Accept attribute in input tag of type file needs filename extensions, starting with a period (".") character. +FILE_ACCEPT_ATTR_VALUE = ", ".join(['.' + ext for ext in FILE_ALLOWED_EXTENSIONS]) + # Hijack Settings HIJACK_LOGIN_REDIRECT_URL = '/dashboard/' HIJACK_LOGOUT_REDIRECT_URL = '/account/'