Fixed #8918 -- Made FileField.upload_to optional.
Thanks leahculver for the suggestion and dc and vajrasky for work on the patch.
This commit is contained in:
parent
b67ab75e82
commit
945e033a69
|
@ -120,8 +120,6 @@ def get_validation_errors(outfile, app=None):
|
||||||
if decimalp_ok and mdigits_ok:
|
if decimalp_ok and mdigits_ok:
|
||||||
if decimal_places > max_digits:
|
if decimal_places > max_digits:
|
||||||
e.add(opts, invalid_values_msg % f.name)
|
e.add(opts, invalid_values_msg % f.name)
|
||||||
if isinstance(f, models.FileField) and not f.upload_to:
|
|
||||||
e.add(opts, '"%s": FileFields require an "upload_to" attribute.' % f.name)
|
|
||||||
if isinstance(f, models.ImageField):
|
if isinstance(f, models.ImageField):
|
||||||
try:
|
try:
|
||||||
from django.utils.image import Image
|
from django.utils.image import Image
|
||||||
|
|
|
@ -45,10 +45,9 @@ Using a :class:`~django.db.models.FileField` or an
|
||||||
account.
|
account.
|
||||||
|
|
||||||
#. Add the :class:`~django.db.models.FileField` or
|
#. Add the :class:`~django.db.models.FileField` or
|
||||||
:class:`~django.db.models.ImageField` to your model, making sure to
|
:class:`~django.db.models.ImageField` to your model, defining the
|
||||||
define the :attr:`~django.db.models.FileField.upload_to` option to tell
|
:attr:`~django.db.models.FileField.upload_to` option to specify a
|
||||||
Django to which subdirectory of :setting:`MEDIA_ROOT` it should upload
|
subdirectory of :setting:`MEDIA_ROOT` to use for uploaded files.
|
||||||
files.
|
|
||||||
|
|
||||||
#. All that will be stored in your database is a path to the file
|
#. All that will be stored in your database is a path to the file
|
||||||
(relative to :setting:`MEDIA_ROOT`). You'll most likely want to use the
|
(relative to :setting:`MEDIA_ROOT`). You'll most likely want to use the
|
||||||
|
|
|
@ -542,7 +542,7 @@ A :class:`CharField` that checks that the value is a valid email address.
|
||||||
``FileField``
|
``FileField``
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
.. class:: FileField(upload_to=None, [max_length=100, **options])
|
.. class:: FileField([upload_to=None, max_length=100, **options])
|
||||||
|
|
||||||
A file-upload field.
|
A file-upload field.
|
||||||
|
|
||||||
|
@ -550,10 +550,14 @@ A file-upload field.
|
||||||
The ``primary_key`` and ``unique`` arguments are not supported, and will
|
The ``primary_key`` and ``unique`` arguments are not supported, and will
|
||||||
raise a ``TypeError`` if used.
|
raise a ``TypeError`` if used.
|
||||||
|
|
||||||
Has one **required** argument:
|
Has two optional arguments:
|
||||||
|
|
||||||
.. attribute:: FileField.upload_to
|
.. attribute:: FileField.upload_to
|
||||||
|
|
||||||
|
.. versionchanged:: 1.7
|
||||||
|
|
||||||
|
``upload_to`` was required in older versions of Django.
|
||||||
|
|
||||||
A local filesystem path that will be appended to your :setting:`MEDIA_ROOT`
|
A local filesystem path that will be appended to your :setting:`MEDIA_ROOT`
|
||||||
setting to determine the value of the
|
setting to determine the value of the
|
||||||
:attr:`~django.db.models.fields.files.FieldFile.url` attribute.
|
:attr:`~django.db.models.fields.files.FieldFile.url` attribute.
|
||||||
|
@ -586,11 +590,9 @@ Has one **required** argument:
|
||||||
when determining the final destination path.
|
when determining the final destination path.
|
||||||
====================== ===============================================
|
====================== ===============================================
|
||||||
|
|
||||||
Also has one optional argument:
|
|
||||||
|
|
||||||
.. attribute:: FileField.storage
|
.. attribute:: FileField.storage
|
||||||
|
|
||||||
Optional. A storage object, which handles the storage and retrieval of your
|
A storage object, which handles the storage and retrieval of your
|
||||||
files. See :doc:`/topics/files` for details on how to provide this object.
|
files. See :doc:`/topics/files` for details on how to provide this object.
|
||||||
|
|
||||||
The default form widget for this field is a :class:`~django.forms.FileInput`.
|
The default form widget for this field is a :class:`~django.forms.FileInput`.
|
||||||
|
@ -604,9 +606,9 @@ takes a few steps:
|
||||||
:setting:`MEDIA_URL` as the base public URL of that directory. Make sure
|
:setting:`MEDIA_URL` as the base public URL of that directory. Make sure
|
||||||
that this directory is writable by the Web server's user account.
|
that this directory is writable by the Web server's user account.
|
||||||
|
|
||||||
2. Add the :class:`FileField` or :class:`ImageField` to your model, making
|
2. Add the :class:`FileField` or :class:`ImageField` to your model, defining
|
||||||
sure to define the :attr:`~FileField.upload_to` option to tell Django
|
the :attr:`~FileField.upload_to` option to specify a subdirectory of
|
||||||
to which subdirectory of :setting:`MEDIA_ROOT` it should upload files.
|
:setting:`MEDIA_ROOT` to use for uploaded files.
|
||||||
|
|
||||||
3. All that will be stored in your database is a path to the file
|
3. All that will be stored in your database is a path to the file
|
||||||
(relative to :setting:`MEDIA_ROOT`). You'll most likely want to use the
|
(relative to :setting:`MEDIA_ROOT`). You'll most likely want to use the
|
||||||
|
@ -807,7 +809,7 @@ The default form widget for this field is a :class:`~django.forms.TextInput`.
|
||||||
``ImageField``
|
``ImageField``
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
.. class:: ImageField(upload_to=None, [height_field=None, width_field=None, max_length=100, **options])
|
.. class:: ImageField([upload_to=None, height_field=None, width_field=None, max_length=100, **options])
|
||||||
|
|
||||||
Inherits all attributes and methods from :class:`FileField`, but also
|
Inherits all attributes and methods from :class:`FileField`, but also
|
||||||
validates that the uploaded object is a valid image.
|
validates that the uploaded object is a valid image.
|
||||||
|
|
|
@ -246,6 +246,10 @@ File Uploads
|
||||||
the file system permissions of directories created during file upload, like
|
the file system permissions of directories created during file upload, like
|
||||||
:setting:`FILE_UPLOAD_PERMISSIONS` does for the files themselves.
|
:setting:`FILE_UPLOAD_PERMISSIONS` does for the files themselves.
|
||||||
|
|
||||||
|
* The :attr:`FileField.upload_to <django.db.models.FileField.upload_to>`
|
||||||
|
attribute is now optional. If it is omitted or given ``None`` or an empty
|
||||||
|
string, a subdirectory won't be used for storing the uploaded files.
|
||||||
|
|
||||||
Forms
|
Forms
|
||||||
^^^^^
|
^^^^^
|
||||||
|
|
||||||
|
|
|
@ -28,3 +28,4 @@ class Storage(models.Model):
|
||||||
custom = models.FileField(storage=temp_storage, upload_to=custom_upload_to)
|
custom = models.FileField(storage=temp_storage, upload_to=custom_upload_to)
|
||||||
random = models.FileField(storage=temp_storage, upload_to=random_upload_to)
|
random = models.FileField(storage=temp_storage, upload_to=random_upload_to)
|
||||||
default = models.FileField(storage=temp_storage, upload_to='tests', default='tests/default.txt')
|
default = models.FileField(storage=temp_storage, upload_to='tests', default='tests/default.txt')
|
||||||
|
empty = models.FileField(storage=temp_storage)
|
||||||
|
|
|
@ -106,6 +106,12 @@ class FileStorageTests(TestCase):
|
||||||
obj4.random.save("random_file", ContentFile("random content"))
|
obj4.random.save("random_file", ContentFile("random content"))
|
||||||
self.assertTrue(obj4.random.name.endswith("/random_file"))
|
self.assertTrue(obj4.random.name.endswith("/random_file"))
|
||||||
|
|
||||||
|
# upload_to can be empty, meaning it does not use subdirectory.
|
||||||
|
obj5 = Storage()
|
||||||
|
obj5.empty.save('django_test.txt', ContentFile('more content'))
|
||||||
|
self.assertEqual(obj5.empty.name, "./django_test.txt")
|
||||||
|
self.assertEqual(obj5.empty.read(), b"more content")
|
||||||
|
|
||||||
def test_file_object(self):
|
def test_file_object(self):
|
||||||
# Create sample file
|
# Create sample file
|
||||||
temp_storage.save('tests/example.txt', ContentFile('some content'))
|
temp_storage.save('tests/example.txt', ContentFile('some content'))
|
||||||
|
|
|
@ -19,7 +19,6 @@ class FieldErrors(models.Model):
|
||||||
decimalfield3 = models.DecimalField(max_digits="bad", decimal_places="bad")
|
decimalfield3 = models.DecimalField(max_digits="bad", decimal_places="bad")
|
||||||
decimalfield4 = models.DecimalField(max_digits=9, decimal_places=10)
|
decimalfield4 = models.DecimalField(max_digits=9, decimal_places=10)
|
||||||
decimalfield5 = models.DecimalField(max_digits=10, decimal_places=10)
|
decimalfield5 = models.DecimalField(max_digits=10, decimal_places=10)
|
||||||
filefield = models.FileField()
|
|
||||||
choices = models.CharField(max_length=10, choices='bad')
|
choices = models.CharField(max_length=10, choices='bad')
|
||||||
choices2 = models.CharField(max_length=10, choices=[(1, 2, 3), (1, 2, 3)])
|
choices2 = models.CharField(max_length=10, choices=[(1, 2, 3), (1, 2, 3)])
|
||||||
index = models.CharField(max_length=10, db_index='bad')
|
index = models.CharField(max_length=10, db_index='bad')
|
||||||
|
@ -424,7 +423,6 @@ invalid_models.fielderrors: "decimalfield2": DecimalFields require a "max_digits
|
||||||
invalid_models.fielderrors: "decimalfield3": DecimalFields require a "decimal_places" attribute that is a non-negative integer.
|
invalid_models.fielderrors: "decimalfield3": DecimalFields require a "decimal_places" attribute that is a non-negative integer.
|
||||||
invalid_models.fielderrors: "decimalfield3": DecimalFields require a "max_digits" attribute that is a positive integer.
|
invalid_models.fielderrors: "decimalfield3": DecimalFields require a "max_digits" attribute that is a positive integer.
|
||||||
invalid_models.fielderrors: "decimalfield4": DecimalFields require a "max_digits" attribute value that is greater than or equal to the value of the "decimal_places" attribute.
|
invalid_models.fielderrors: "decimalfield4": DecimalFields require a "max_digits" attribute value that is greater than or equal to the value of the "decimal_places" attribute.
|
||||||
invalid_models.fielderrors: "filefield": FileFields require an "upload_to" attribute.
|
|
||||||
invalid_models.fielderrors: "choices": "choices" should be iterable (e.g., a tuple or list).
|
invalid_models.fielderrors: "choices": "choices" should be iterable (e.g., a tuple or list).
|
||||||
invalid_models.fielderrors: "choices2": "choices" should be a sequence of two-item iterables (e.g. list of 2 item tuples).
|
invalid_models.fielderrors: "choices2": "choices" should be a sequence of two-item iterables (e.g. list of 2 item tuples).
|
||||||
invalid_models.fielderrors: "choices2": "choices" should be a sequence of two-item iterables (e.g. list of 2 item tuples).
|
invalid_models.fielderrors: "choices2": "choices" should be a sequence of two-item iterables (e.g. list of 2 item tuples).
|
||||||
|
|
Loading…
Reference in New Issue