Fixed #31118 -- Made FileInput to avoid the required attribute when initial data exists.
This commit is contained in:
parent
53d8646f79
commit
ffcf1a8ebf
|
@ -387,6 +387,9 @@ class FileInput(Input):
|
||||||
def value_omitted_from_data(self, data, files, name):
|
def value_omitted_from_data(self, data, files, name):
|
||||||
return name not in files
|
return name not in files
|
||||||
|
|
||||||
|
def use_required_attribute(self, initial):
|
||||||
|
return super().use_required_attribute(initial) and not initial
|
||||||
|
|
||||||
|
|
||||||
FILE_INPUT_CONTRADICTION = object()
|
FILE_INPUT_CONTRADICTION = object()
|
||||||
|
|
||||||
|
@ -451,9 +454,6 @@ class ClearableFileInput(FileInput):
|
||||||
return False
|
return False
|
||||||
return upload
|
return upload
|
||||||
|
|
||||||
def use_required_attribute(self, initial):
|
|
||||||
return super().use_required_attribute(initial) and not initial
|
|
||||||
|
|
||||||
def value_omitted_from_data(self, data, files, name):
|
def value_omitted_from_data(self, data, files, name):
|
||||||
return (
|
return (
|
||||||
super().value_omitted_from_data(data, files, name) and
|
super().value_omitted_from_data(data, files, name) and
|
||||||
|
|
|
@ -325,17 +325,22 @@ foundation for custom widgets.
|
||||||
to display the ``required`` attribute for each field.
|
to display the ``required`` attribute for each field.
|
||||||
|
|
||||||
By default, returns ``False`` for hidden widgets and ``True``
|
By default, returns ``False`` for hidden widgets and ``True``
|
||||||
otherwise. Special cases are :class:`~django.forms.ClearableFileInput`,
|
otherwise. Special cases are :class:`~django.forms.FileInput` and
|
||||||
which returns ``False`` when ``initial`` is set, and
|
:class:`~django.forms.ClearableFileInput`, which return ``False`` when
|
||||||
:class:`~django.forms.CheckboxSelectMultiple`, which always returns
|
``initial`` is set, and :class:`~django.forms.CheckboxSelectMultiple`,
|
||||||
``False`` because browser validation would require all checkboxes to be
|
which always returns ``False`` because browser validation would require
|
||||||
checked instead of at least one.
|
all checkboxes to be checked instead of at least one.
|
||||||
|
|
||||||
Override this method in custom widgets that aren't compatible with
|
Override this method in custom widgets that aren't compatible with
|
||||||
browser validation. For example, a WSYSIWG text editor widget backed by
|
browser validation. For example, a WSYSIWG text editor widget backed by
|
||||||
a hidden ``textarea`` element may want to always return ``False`` to
|
a hidden ``textarea`` element may want to always return ``False`` to
|
||||||
avoid browser validation on the hidden field.
|
avoid browser validation on the hidden field.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.1
|
||||||
|
|
||||||
|
In older versions, ``True`` was returned for
|
||||||
|
:class:`~django.forms.FileInput` when ``initial`` was set.
|
||||||
|
|
||||||
``MultiWidget``
|
``MultiWidget``
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
|
|
@ -406,6 +406,9 @@ Miscellaneous
|
||||||
* Date-only formats are removed from the default list for
|
* Date-only formats are removed from the default list for
|
||||||
:setting:`DATETIME_INPUT_FORMATS`.
|
:setting:`DATETIME_INPUT_FORMATS`.
|
||||||
|
|
||||||
|
* The :class:`~django.forms.FileInput` widget no longer renders with the
|
||||||
|
``required`` HTML attribute when initial data exists.
|
||||||
|
|
||||||
.. _deprecated-features-3.1:
|
.. _deprecated-features-3.1:
|
||||||
|
|
||||||
Features deprecated in 3.1
|
Features deprecated in 3.1
|
||||||
|
|
|
@ -8,11 +8,11 @@ from django.core.files.uploadedfile import SimpleUploadedFile
|
||||||
from django.core.validators import MaxValueValidator, RegexValidator
|
from django.core.validators import MaxValueValidator, RegexValidator
|
||||||
from django.forms import (
|
from django.forms import (
|
||||||
BooleanField, CharField, CheckboxSelectMultiple, ChoiceField, DateField,
|
BooleanField, CharField, CheckboxSelectMultiple, ChoiceField, DateField,
|
||||||
DateTimeField, EmailField, FileField, FloatField, Form, HiddenInput,
|
DateTimeField, EmailField, FileField, FileInput, FloatField, Form,
|
||||||
ImageField, IntegerField, MultipleChoiceField, MultipleHiddenInput,
|
HiddenInput, ImageField, IntegerField, MultipleChoiceField,
|
||||||
MultiValueField, NullBooleanField, PasswordInput, RadioSelect, Select,
|
MultipleHiddenInput, MultiValueField, NullBooleanField, PasswordInput,
|
||||||
SplitDateTimeField, SplitHiddenDateTimeWidget, Textarea, TextInput,
|
RadioSelect, Select, SplitDateTimeField, SplitHiddenDateTimeWidget,
|
||||||
TimeField, ValidationError, forms,
|
Textarea, TextInput, TimeField, ValidationError, forms,
|
||||||
)
|
)
|
||||||
from django.forms.renderers import DjangoTemplates, get_default_renderer
|
from django.forms.renderers import DjangoTemplates, get_default_renderer
|
||||||
from django.forms.utils import ErrorList
|
from django.forms.utils import ErrorList
|
||||||
|
@ -2486,6 +2486,25 @@ Password: <input type="password" name="password" required>
|
||||||
self.assertEqual(f.errors, {})
|
self.assertEqual(f.errors, {})
|
||||||
self.assertEqual(f.cleaned_data['file1'], 'resume.txt')
|
self.assertEqual(f.cleaned_data['file1'], 'resume.txt')
|
||||||
|
|
||||||
|
def test_filefield_with_fileinput_required(self):
|
||||||
|
class FileForm(Form):
|
||||||
|
file1 = forms.FileField(widget=FileInput)
|
||||||
|
|
||||||
|
f = FileForm(auto_id=False)
|
||||||
|
self.assertHTMLEqual(
|
||||||
|
f.as_table(),
|
||||||
|
'<tr><th>File1:</th><td>'
|
||||||
|
'<input type="file" name="file1" required></td></tr>',
|
||||||
|
)
|
||||||
|
# A required file field with initial data doesn't contain the required
|
||||||
|
# HTML attribute. The file input is left blank by the user to keep the
|
||||||
|
# existing, initial value.
|
||||||
|
f = FileForm(initial={'file1': 'resume.txt'}, auto_id=False)
|
||||||
|
self.assertHTMLEqual(
|
||||||
|
f.as_table(),
|
||||||
|
'<tr><th>File1:</th><td><input type="file" name="file1"></td></tr>',
|
||||||
|
)
|
||||||
|
|
||||||
def test_basic_processing_in_view(self):
|
def test_basic_processing_in_view(self):
|
||||||
class UserRegistration(Form):
|
class UserRegistration(Form):
|
||||||
username = CharField(max_length=10)
|
username = CharField(max_length=10)
|
||||||
|
|
|
@ -18,3 +18,9 @@ class FileInputTest(WidgetTest):
|
||||||
def test_value_omitted_from_data(self):
|
def test_value_omitted_from_data(self):
|
||||||
self.assertIs(self.widget.value_omitted_from_data({}, {}, 'field'), True)
|
self.assertIs(self.widget.value_omitted_from_data({}, {}, 'field'), True)
|
||||||
self.assertIs(self.widget.value_omitted_from_data({}, {'field': 'value'}, 'field'), False)
|
self.assertIs(self.widget.value_omitted_from_data({}, {'field': 'value'}, 'field'), False)
|
||||||
|
|
||||||
|
def test_use_required_attribute(self):
|
||||||
|
# False when initial data exists. The file input is left blank by the
|
||||||
|
# user to keep the existing, initial value.
|
||||||
|
self.assertIs(self.widget.use_required_attribute(None), True)
|
||||||
|
self.assertIs(self.widget.use_required_attribute('resume.txt'), False)
|
||||||
|
|
Loading…
Reference in New Issue