Fixed #29205 -- Corrected rendering of required attributes for MultiValueField subfields.
This commit is contained in:
parent
db1fc5cd3c
commit
2d0ae8da80
|
@ -2,7 +2,7 @@ import re
|
||||||
|
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.forms.utils import flatatt, pretty_name
|
from django.forms.utils import flatatt, pretty_name
|
||||||
from django.forms.widgets import Textarea, TextInput
|
from django.forms.widgets import MultiWidget, Textarea, TextInput
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
from django.utils.html import conditional_escape, format_html, html_safe
|
from django.utils.html import conditional_escape, format_html, html_safe
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
|
@ -233,7 +233,17 @@ class BoundField:
|
||||||
widget = widget or self.field.widget
|
widget = widget or self.field.widget
|
||||||
attrs = dict(attrs) # Copy attrs to avoid modifying the argument.
|
attrs = dict(attrs) # Copy attrs to avoid modifying the argument.
|
||||||
if widget.use_required_attribute(self.initial) and self.field.required and self.form.use_required_attribute:
|
if widget.use_required_attribute(self.initial) and self.field.required and self.form.use_required_attribute:
|
||||||
attrs['required'] = True
|
# MultiValueField has require_all_fields: if False, fall back
|
||||||
|
# on subfields.
|
||||||
|
if (
|
||||||
|
hasattr(self.field, 'require_all_fields') and
|
||||||
|
not self.field.require_all_fields and
|
||||||
|
isinstance(self.field.widget, MultiWidget)
|
||||||
|
):
|
||||||
|
for subfield, subwidget in zip(self.field.fields, widget.widgets):
|
||||||
|
subwidget.attrs['required'] = subwidget.use_required_attribute(self.initial) and subfield.required
|
||||||
|
else:
|
||||||
|
attrs['required'] = True
|
||||||
if self.field.disabled:
|
if self.field.disabled:
|
||||||
attrs['disabled'] = True
|
attrs['disabled'] = True
|
||||||
return attrs
|
return attrs
|
||||||
|
|
|
@ -10,6 +10,20 @@ from django.test import SimpleTestCase
|
||||||
beatles = (('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))
|
beatles = (('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))
|
||||||
|
|
||||||
|
|
||||||
|
class PartiallyRequiredField(MultiValueField):
|
||||||
|
def compress(self, data_list):
|
||||||
|
return ','.join(data_list) if data_list else None
|
||||||
|
|
||||||
|
|
||||||
|
class PartiallyRequiredForm(Form):
|
||||||
|
f = PartiallyRequiredField(
|
||||||
|
fields=(CharField(required=True), CharField(required=False)),
|
||||||
|
required=True,
|
||||||
|
require_all_fields=False,
|
||||||
|
widget=MultiWidget(widgets=[TextInput(), TextInput()]),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ComplexMultiWidget(MultiWidget):
|
class ComplexMultiWidget(MultiWidget):
|
||||||
def __init__(self, attrs=None):
|
def __init__(self, attrs=None):
|
||||||
widgets = (
|
widgets = (
|
||||||
|
@ -172,3 +186,11 @@ class MultiValueFieldTest(SimpleTestCase):
|
||||||
})
|
})
|
||||||
form.is_valid()
|
form.is_valid()
|
||||||
self.assertEqual(form.cleaned_data['field1'], 'some text,JP,2007-04-25 06:24:00')
|
self.assertEqual(form.cleaned_data['field1'], 'some text,JP,2007-04-25 06:24:00')
|
||||||
|
|
||||||
|
def test_render_required_attributes(self):
|
||||||
|
form = PartiallyRequiredForm({'f_0': 'Hello', 'f_1': ''})
|
||||||
|
self.assertTrue(form.is_valid())
|
||||||
|
self.assertInHTML('<input type="text" name="f_0" value="Hello" required id="id_f_0">', form.as_p())
|
||||||
|
self.assertInHTML('<input type="text" name="f_1" id="id_f_1">', form.as_p())
|
||||||
|
form = PartiallyRequiredForm({'f_0': '', 'f_1': ''})
|
||||||
|
self.assertFalse(form.is_valid())
|
||||||
|
|
Loading…
Reference in New Issue