From 7cddd8a02e60332c0d02f565c450b0eea0d88438 Mon Sep 17 00:00:00 2001 From: Henry Dang Date: Sat, 26 Nov 2016 13:23:03 -0500 Subject: [PATCH] Fixed #27358 -- Added a system check to prevent FileField's upload_to from starting with a slash. Thanks Frank Bijlsma for the initial patch. --- django/db/models/fields/files.py | 15 +++++++++++ docs/ref/checks.txt | 2 ++ .../test_ordinary_fields.py | 25 +++++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/django/db/models/fields/files.py b/django/db/models/fields/files.py index e3497f2494..53a31c3ed6 100644 --- a/django/db/models/fields/files.py +++ b/django/db/models/fields/files.py @@ -240,6 +240,7 @@ class FileField(Field): def check(self, **kwargs): errors = super(FileField, self).check(**kwargs) errors.extend(self._check_primary_key()) + errors.extend(self._check_upload_to()) return errors def _check_primary_key(self): @@ -254,6 +255,20 @@ class FileField(Field): else: return [] + def _check_upload_to(self): + if isinstance(self.upload_to, six.string_types) and self.upload_to[0] == '/': + return [ + checks.Error( + "%s's 'upload_to' argument must be a relative path, not an " + "absolute path." % self.__class__.__name__, + obj=self, + id='fields.E202', + hint='Remove the leading slash.', + ) + ] + else: + return [] + def deconstruct(self): name, path, args, kwargs = super(FileField, self).deconstruct() if kwargs.get("max_length") == 100: diff --git a/docs/ref/checks.txt b/docs/ref/checks.txt index a3c659aad5..1f35c5bb0f 100644 --- a/docs/ref/checks.txt +++ b/docs/ref/checks.txt @@ -189,6 +189,8 @@ File Fields * **fields.E200**: ``unique`` is not a valid argument for a ``FileField``. *This check is removed in Django 1.11*. * **fields.E201**: ``primary_key`` is not a valid argument for a ``FileField``. +* **fields.E202**: ``FileField``’s ``upload_to`` argument must be a relative + path, not an absolute path. * **fields.E210**: Cannot use ``ImageField`` because Pillow is not installed. Related Fields diff --git a/tests/invalid_models_tests/test_ordinary_fields.py b/tests/invalid_models_tests/test_ordinary_fields.py index aff6a74659..c005fe9331 100644 --- a/tests/invalid_models_tests/test_ordinary_fields.py +++ b/tests/invalid_models_tests/test_ordinary_fields.py @@ -455,6 +455,31 @@ class FileFieldTests(SimpleTestCase): ] self.assertEqual(errors, expected) + def test_upload_to_starts_with_slash(self): + class Model(models.Model): + field = models.FileField(upload_to='/somewhere') + + field = Model._meta.get_field('field') + self.assertEqual(field.check(), [ + Error( + "FileField's 'upload_to' argument must be a relative path, not " + "an absolute path.", + obj=field, + id='fields.E202', + hint='Remove the leading slash.', + ) + ]) + + def test_upload_to_callable_not_checked(self): + def callable(instance, filename): + return '/' + filename + + class Model(models.Model): + field = models.FileField(upload_to=callable) + + field = Model._meta.get_field('field') + self.assertEqual(field.check(), []) + @isolate_apps('invalid_models_tests') class FilePathFieldTests(SimpleTestCase):