Refs #28428 -- Made FileField.upload_to support pathlib.Path.

This commit is contained in:
Claude Paroz 2019-08-18 11:40:11 +02:00 committed by Mariusz Felisiak
parent af69842dbd
commit d1c2e6dd04
5 changed files with 14 additions and 4 deletions

View File

@ -302,7 +302,7 @@ class FileField(Field):
if callable(self.upload_to): if callable(self.upload_to):
filename = self.upload_to(instance, filename) filename = self.upload_to(instance, filename)
else: else:
dirname = datetime.datetime.now().strftime(self.upload_to) dirname = datetime.datetime.now().strftime(str(self.upload_to))
filename = posixpath.join(dirname, filename) filename = posixpath.join(dirname, filename)
return self.storage.generate_filename(filename) return self.storage.generate_filename(filename)

View File

@ -629,9 +629,10 @@ Has two optional arguments:
and can be set in two ways. In both cases, the value is passed to the and can be set in two ways. In both cases, the value is passed to the
:meth:`Storage.save() <django.core.files.storage.Storage.save>` method. :meth:`Storage.save() <django.core.files.storage.Storage.save>` method.
If you specify a string value, it may contain :func:`~time.strftime` If you specify a string value or a :class:`~pathlib.Path`, it may contain
formatting, which will be replaced by the date/time of the file upload (so :func:`~time.strftime` formatting, which will be replaced by the date/time
that uploaded files don't fill up the given directory). For example:: of the file upload (so that uploaded files don't fill up the given
directory). For example::
class MyModel(models.Model): class MyModel(models.Model):
# file will be uploaded to MEDIA_ROOT/uploads # file will be uploaded to MEDIA_ROOT/uploads
@ -679,6 +680,10 @@ Has two optional arguments:
class MyModel(models.Model): class MyModel(models.Model):
upload = models.FileField(upload_to=user_directory_path) upload = models.FileField(upload_to=user_directory_path)
.. versionchanged:: 3.0
Support for :class:`pathlib.Path` was added.
.. attribute:: FileField.storage .. attribute:: FileField.storage
A storage object, which handles the storage and retrieval of your A storage object, which handles the storage and retrieval of your

View File

@ -304,6 +304,8 @@ Models
a certain (database-dependent) limit. Values from ``1`` to ``32767`` are safe a certain (database-dependent) limit. Values from ``1`` to ``32767`` are safe
in all databases supported by Django. in all databases supported by Django.
* :attr:`.FileField.upload_to` now supports :class:`pathlib.Path`.
Requests and Responses Requests and Responses
~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~

View File

@ -38,6 +38,7 @@ class Storage(models.Model):
normal = models.FileField(storage=temp_storage, upload_to='tests') normal = models.FileField(storage=temp_storage, upload_to='tests')
custom = models.FileField(storage=temp_storage, upload_to=custom_upload_to) custom = models.FileField(storage=temp_storage, upload_to=custom_upload_to)
pathlib_callable = models.FileField(storage=temp_storage, upload_to=pathlib_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) random = models.FileField(storage=temp_storage, upload_to=random_upload_to)
custom_valid_name = models.FileField( custom_valid_name = models.FileField(
storage=CustomValidNameStorage(location=temp_storage_location), storage=CustomValidNameStorage(location=temp_storage_location),

View File

@ -796,6 +796,8 @@ class FileFieldStorageTests(TestCase):
obj = Storage() obj = Storage()
obj.pathlib_callable.save('some_file1.txt', ContentFile('some content')) obj.pathlib_callable.save('some_file1.txt', ContentFile('some content'))
self.assertEqual(obj.pathlib_callable.name, 'bar/some_file1.txt') 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() obj.random.close()
def test_random_upload_to(self): def test_random_upload_to(self):