diff --git a/django/db/models/fields/files.py b/django/db/models/fields/files.py index 8f12e807253..b03d54366ae 100644 --- a/django/db/models/fields/files.py +++ b/django/db/models/fields/files.py @@ -302,7 +302,7 @@ class FileField(Field): if callable(self.upload_to): filename = self.upload_to(instance, filename) else: - dirname = datetime.datetime.now().strftime(self.upload_to) + dirname = datetime.datetime.now().strftime(str(self.upload_to)) filename = posixpath.join(dirname, filename) return self.storage.generate_filename(filename) diff --git a/docs/ref/models/fields.txt b/docs/ref/models/fields.txt index c267501bf44..01a56c13128 100644 --- a/docs/ref/models/fields.txt +++ b/docs/ref/models/fields.txt @@ -629,9 +629,10 @@ Has two optional arguments: and can be set in two ways. In both cases, the value is passed to the :meth:`Storage.save() ` method. - If you specify a string value, it may contain :func:`~time.strftime` - formatting, which will be replaced by the date/time of the file upload (so - that uploaded files don't fill up the given directory). For example:: + If you specify a string value or a :class:`~pathlib.Path`, it may contain + :func:`~time.strftime` formatting, which will be replaced by the date/time + of the file upload (so that uploaded files don't fill up the given + directory). For example:: class MyModel(models.Model): # file will be uploaded to MEDIA_ROOT/uploads @@ -679,6 +680,10 @@ Has two optional arguments: class MyModel(models.Model): upload = models.FileField(upload_to=user_directory_path) + .. versionchanged:: 3.0 + + Support for :class:`pathlib.Path` was added. + .. attribute:: FileField.storage A storage object, which handles the storage and retrieval of your diff --git a/docs/releases/3.0.txt b/docs/releases/3.0.txt index b6b33683378..2e345f6fe5c 100644 --- a/docs/releases/3.0.txt +++ b/docs/releases/3.0.txt @@ -304,6 +304,8 @@ Models a certain (database-dependent) limit. Values from ``1`` to ``32767`` are safe in all databases supported by Django. +* :attr:`.FileField.upload_to` now supports :class:`pathlib.Path`. + Requests and Responses ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/tests/file_storage/models.py b/tests/file_storage/models.py index 96805f6ad59..8085a8bb1aa 100644 --- a/tests/file_storage/models.py +++ b/tests/file_storage/models.py @@ -38,6 +38,7 @@ class Storage(models.Model): normal = models.FileField(storage=temp_storage, upload_to='tests') custom = models.FileField(storage=temp_storage, upload_to=custom_upload_to) pathlib_callable = models.FileField(storage=temp_storage, upload_to=pathlib_upload_to) + pathlib_direct = models.FileField(storage=temp_storage, upload_to=Path('bar')) random = models.FileField(storage=temp_storage, upload_to=random_upload_to) custom_valid_name = models.FileField( storage=CustomValidNameStorage(location=temp_storage_location), diff --git a/tests/file_storage/tests.py b/tests/file_storage/tests.py index 6edfd2902c4..1c4176014c5 100644 --- a/tests/file_storage/tests.py +++ b/tests/file_storage/tests.py @@ -796,6 +796,8 @@ class FileFieldStorageTests(TestCase): obj = Storage() obj.pathlib_callable.save('some_file1.txt', ContentFile('some content')) self.assertEqual(obj.pathlib_callable.name, 'bar/some_file1.txt') + obj.pathlib_direct.save('some_file2.txt', ContentFile('some content')) + self.assertEqual(obj.pathlib_direct.name, 'bar/some_file2.txt') obj.random.close() def test_random_upload_to(self):