Skip to content

Commit

Permalink
Merge pull request #1350 from maykinmedia/limited-file-upload-field-o…
Browse files Browse the repository at this point in the history
…verridable-params

Make parameters of LimitedUploadFileField overridable
  • Loading branch information
alextreme authored Aug 15, 2024
2 parents b08b824 + eea5b97 commit da884ce
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 13 deletions.
4 changes: 2 additions & 2 deletions src/open_inwoner/accounts/tests/test_file_upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def test_invalid_type_of_file_is_not_uploaded(self):
upload_response.context["errors"],
[
_(
"Het type bestand dat u hebt geüpload is ongeldig. Geldige bestandstypen zijn: pdf, docx, doc, xlsx, xls, jpeg, jpg, png, txt, odt, odf, ods"
"Het type bestand dat u hebt geüpload is ongeldig. Geldige bestandstypen zijn: docx, doc, xlsx, xls, txt, odt, odf, ods, pdf, jpg, png"
)
],
)
Expand Down Expand Up @@ -116,7 +116,7 @@ def test_invalid_type_of_file_is_not_uploaded(self):
upload_response.context["errors"],
[
_(
"Het type bestand dat u hebt geüpload is ongeldig. Geldige bestandstypen zijn: pdf, docx, doc, xlsx, xls, jpeg, jpg, png, txt, odt, odf, ods"
"Het type bestand dat u hebt geüpload is ongeldig. Geldige bestandstypen zijn: docx, doc, xlsx, xls, txt, odt, odf, ods, pdf, jpg, png"
)
],
)
Expand Down
65 changes: 54 additions & 11 deletions src/open_inwoner/utils/forms.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import mimetypes

from django import forms
from django.conf import settings
from django.core.files.uploadedfile import InMemoryUploadedFile, TemporaryUploadedFile
Expand Down Expand Up @@ -86,37 +88,78 @@ class LimitedUploadFileField(forms.FileField):
"Een aangeleverd bestand dient maximaal %(size)s te zijn, uw bestand is te groot."
),
"file_type": _(
"Het type bestand dat u hebt geüpload is ongeldig. Geldige bestandstypen zijn: pdf, docx, doc, xlsx, xls, jpeg, jpg, png, txt, odt, odf, ods"
"Het type bestand dat u hebt geüpload is ongeldig. Geldige bestandstypen zijn: %(file_extensions)s"
),
}

def __init__(
self,
*args,
min_upload_size: int | None = None,
max_upload_size: int | None = None,
allowed_mime_types: list[str] | None = None,
**kwargs,
):
self._min_upload_size = min_upload_size
self._max_upload_size = max_upload_size
self._allowed_mime_types = allowed_mime_types or []

for mt in self._allowed_mime_types:
if not mimetypes.guess_extension(mt):
raise ValueError(f"Cannot guess extension for mimetype {mt}")

super().__init__(*args, **kwargs)

@property
def min_upload_size(self):
return self._min_upload_size or settings.MIN_UPLOAD_SIZE

@property
def max_upload_size(self):
return self._max_upload_size or settings.MAX_UPLOAD_SIZE

@property
def allowed_mime_types(self):
return (
",".join(self._allowed_mime_types)
if self._allowed_mime_types
else settings.UPLOAD_FILE_TYPES
)

@property
def allowed_extensions(self):
return [
mimetypes.guess_extension(mt)[1:]
for mt in self.allowed_mime_types.split(",")
]

def widget_attrs(self, widget):
attrs = super().widget_attrs(widget)
attrs.update({"accept": settings.UPLOAD_FILE_TYPES})
attrs.update({"accept": self.allowed_mime_types})
return attrs

def clean(self, *args, **kwargs):
f = super().clean(*args, **kwargs)

if isinstance(f, InMemoryUploadedFile) or isinstance(f, TemporaryUploadedFile):
_error_messages = self.upload_error_messages
min_upload_size = settings.MIN_UPLOAD_SIZE
max_upload_size = settings.MAX_UPLOAD_SIZE
file_types = settings.UPLOAD_FILE_TYPES

# checking file size limits
if f.size < min_upload_size:
if f.size < self.min_upload_size:
raise forms.ValidationError(
_error_messages["min_size"],
params={"size": filesizeformat(min_upload_size)},
params={"size": filesizeformat(self.min_upload_size)},
)
if f.size > max_upload_size:
if f.size > self.max_upload_size:
raise forms.ValidationError(
_error_messages["max_size"],
params={"size": filesizeformat(max_upload_size)},
params={"size": filesizeformat(self.max_upload_size)},
)
# checking file type limits
if f.content_type not in file_types.split(","):
raise forms.ValidationError(_error_messages["file_type"])
if f.content_type not in self.allowed_mime_types.split(","):
raise forms.ValidationError(
_error_messages["file_type"]
% {"file_extensions": ", ".join(self.allowed_extensions)}
)

return f
74 changes: 74 additions & 0 deletions src/open_inwoner/utils/tests/test_limited_file_upload_field.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
from unittest import TestCase

from django.core.files.uploadedfile import SimpleUploadedFile
from django.forms import Form

from open_inwoner.utils.forms import LimitedUploadFileField


def form_class_factory(*args, **kwargs):
class TestForm(Form):
file = LimitedUploadFileField(*args, **kwargs)

return TestForm


class LimitedUploadFileFieldTests(TestCase):
def test_title_starting_lowercase(self):

with self.assertRaises(ValueError):
form_class_factory(allowed_mime_types=["i-am-not-a/valid-mime-type"])

def test_file_too_small(self):
TestForm = form_class_factory(min_upload_size=2)
form = TestForm(
files={
"file": SimpleUploadedFile(
"test_file.txt", b"1", content_type="application/pdf"
)
}
)
form.is_valid()

self.assertEqual(
form.errors["file"],
[
"Een aangeleverd bestand dient minimaal 2\xa0bytes te zijn, uw bestand is te klein."
],
)

def test_file_too_big(self):
TestForm = form_class_factory(max_upload_size=2)
form = TestForm(
files={
"file": SimpleUploadedFile(
"test_file.txt", b"111", content_type="application/pdf"
)
}
)
form.is_valid()

self.assertEqual(
form.errors["file"],
[
"Een aangeleverd bestand dient maximaal 2\xa0bytes te zijn, uw bestand is te groot."
],
)

def test_file_has_wrong_type(self):
TestForm = form_class_factory()
form = TestForm(
files={
"file": SimpleUploadedFile(
"test_file.txt", b"111", content_type="i-am-not-a/valid-mime-type"
)
}
)
form.is_valid()

self.assertEqual(
form.errors["file"],
[
"Het type bestand dat u hebt geüpload is ongeldig. Geldige bestandstypen zijn: docx, doc, xlsx, xls, txt, odt, odf, ods, pdf, jpg, png"
],
)

0 comments on commit da884ce

Please sign in to comment.