summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShubham singh <shubham1.singh15@gmail.com>2020-01-05 13:21:33 +0530
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2020-01-08 09:15:31 +0100
commitffcf1a8ebfbdc8e3afac84aed88d6ed29a57c72b (patch)
tree926c2b0ff48cb97bf5aba5a3fe2e12bff7a3b6c6
parent53d8646f799de7f92ab9defe9dc56c6125448102 (diff)
downloaddjango-ffcf1a8ebfbdc8e3afac84aed88d6ed29a57c72b.tar.gz
Fixed #31118 -- Made FileInput to avoid the required attribute when initial data exists.
-rw-r--r--django/forms/widgets.py6
-rw-r--r--docs/ref/forms/widgets.txt15
-rw-r--r--docs/releases/3.1.txt3
-rw-r--r--tests/forms_tests/tests/test_forms.py29
-rw-r--r--tests/forms_tests/widget_tests/test_fileinput.py6
5 files changed, 46 insertions, 13 deletions
diff --git a/django/forms/widgets.py b/django/forms/widgets.py
index 338d54d72f..40ac1d3162 100644
--- a/django/forms/widgets.py
+++ b/django/forms/widgets.py
@@ -387,6 +387,9 @@ class FileInput(Input):
def value_omitted_from_data(self, data, files, name):
return name not in files
+ def use_required_attribute(self, initial):
+ return super().use_required_attribute(initial) and not initial
+
FILE_INPUT_CONTRADICTION = object()
@@ -451,9 +454,6 @@ class ClearableFileInput(FileInput):
return False
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):
return (
super().value_omitted_from_data(data, files, name) and
diff --git a/docs/ref/forms/widgets.txt b/docs/ref/forms/widgets.txt
index a9c442289c..e986154753 100644
--- a/docs/ref/forms/widgets.txt
+++ b/docs/ref/forms/widgets.txt
@@ -325,17 +325,22 @@ foundation for custom widgets.
to display the ``required`` attribute for each field.
By default, returns ``False`` for hidden widgets and ``True``
- otherwise. Special cases are :class:`~django.forms.ClearableFileInput`,
- which returns ``False`` when ``initial`` is set, and
- :class:`~django.forms.CheckboxSelectMultiple`, which always returns
- ``False`` because browser validation would require all checkboxes to be
- checked instead of at least one.
+ otherwise. Special cases are :class:`~django.forms.FileInput` and
+ :class:`~django.forms.ClearableFileInput`, which return ``False`` when
+ ``initial`` is set, and :class:`~django.forms.CheckboxSelectMultiple`,
+ which always returns ``False`` because browser validation would require
+ all checkboxes to be checked instead of at least one.
Override this method in custom widgets that aren't compatible with
browser validation. For example, a WSYSIWG text editor widget backed by
a hidden ``textarea`` element may want to always return ``False`` to
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``
---------------
diff --git a/docs/releases/3.1.txt b/docs/releases/3.1.txt
index ffffdc0d1b..cdacbd71cd 100644
--- a/docs/releases/3.1.txt
+++ b/docs/releases/3.1.txt
@@ -406,6 +406,9 @@ Miscellaneous
* Date-only formats are removed from the default list for
: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:
Features deprecated in 3.1
diff --git a/tests/forms_tests/tests/test_forms.py b/tests/forms_tests/tests/test_forms.py
index 552f3b866c..e4a8127e15 100644
--- a/tests/forms_tests/tests/test_forms.py
+++ b/tests/forms_tests/tests/test_forms.py
@@ -8,11 +8,11 @@ from django.core.files.uploadedfile import SimpleUploadedFile
from django.core.validators import MaxValueValidator, RegexValidator
from django.forms import (
BooleanField, CharField, CheckboxSelectMultiple, ChoiceField, DateField,
- DateTimeField, EmailField, FileField, FloatField, Form, HiddenInput,
- ImageField, IntegerField, MultipleChoiceField, MultipleHiddenInput,
- MultiValueField, NullBooleanField, PasswordInput, RadioSelect, Select,
- SplitDateTimeField, SplitHiddenDateTimeWidget, Textarea, TextInput,
- TimeField, ValidationError, forms,
+ DateTimeField, EmailField, FileField, FileInput, FloatField, Form,
+ HiddenInput, ImageField, IntegerField, MultipleChoiceField,
+ MultipleHiddenInput, MultiValueField, NullBooleanField, PasswordInput,
+ RadioSelect, Select, SplitDateTimeField, SplitHiddenDateTimeWidget,
+ Textarea, TextInput, TimeField, ValidationError, forms,
)
from django.forms.renderers import DjangoTemplates, get_default_renderer
from django.forms.utils import ErrorList
@@ -2486,6 +2486,25 @@ Password: <input type="password" name="password" required>
self.assertEqual(f.errors, {})
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):
class UserRegistration(Form):
username = CharField(max_length=10)
diff --git a/tests/forms_tests/widget_tests/test_fileinput.py b/tests/forms_tests/widget_tests/test_fileinput.py
index bbd7c7fe52..8eec26253a 100644
--- a/tests/forms_tests/widget_tests/test_fileinput.py
+++ b/tests/forms_tests/widget_tests/test_fileinput.py
@@ -18,3 +18,9 @@ class FileInputTest(WidgetTest):
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': '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)