Fixed #29205 -- MultiValueField ignores a required value of a sub field#12642
Fixed #29205 -- MultiValueField ignores a required value of a sub field#12642smithdc1 wants to merge 6 commits intodjango:masterfrom
Conversation
carltongibson
left a comment
There was a problem hiding this comment.
Hi @smithdc1.
Thanks for this. Good start.
We can work on the code changes. I've left a few initial comments.
More though I'm not sure we've 100% pinned down the exact behaviour change we're looking for in the changes to the test cases.
- I thought if the parent field was not required then it could be emitted entirely.
- Then it looks like we'll need to adjust some of the existing cases (linked in the inline comments). If so we have to pulled out the behaviour change clearly so that we can make sure it's acceptable and document it suitably.
| if isinstance(widget, MultiWidget) or isinstance(self.field.widget, MultiWidget): | ||
| widgets = widget.widgets or self.field.widget.widgets |
There was a problem hiding this comment.
I think leave the original widget = widget or self.field.widget here. Then do the isinstance() check, so that we're no repeating ourselves in the else block.
widgets might then be clearer as subwidgets. (Or such.)
django/forms/boundfield.py
Outdated
| field.required and | ||
| self.form.use_required_attribute | ||
| ): | ||
| widget.attrs["required"] = True |
There was a problem hiding this comment.
Will this permanently adjust the attr on the widget instance?
There was a problem hiding this comment.
Yes, this makes me sad 👎
Having looked at this again (seem to learn something new every day 👍 ) I think I've been 'abusing' the wrong widget in fields.py (next comment) and I'm therefore correcting my error here.
| if (self.required and (self.require_all_fields or f.required)) or ( | ||
| not self.required and not self.require_all_fields and f.required | ||
| ): | ||
| f.required = f.widget.is_required = True | ||
| else: | ||
| f.required = f.widget.is_required = False |
There was a problem hiding this comment.
The conditional here needs a comment at least. (Did we change the rules here?)
There was a problem hiding this comment.
I'm trying to set is_required on the widget, so we can us this later on. My realisation tonight is here I'm changing is_required on the wrong widget. Here I'm setting it on field.widget. What I need to do is set it on widget.widets.widget. Or more simply, it needs to set on the widgets of the MultiWidget rather than the widgets of the fields of the MultiField.
I'm hoping this will simplify all of this a great deal as we can 'just' rely on get_context to do the right thing if we set it up right here. 🤞
Leave it with me and I'll revert after some more thought.
| with self.assertRaisesMessage(ValidationError, "'Enter a complete value.', 'Enter an extension.'"): | ||
| self.assertIsNone(f.clean(None)) | ||
| with self.assertRaisesMessage(ValidationError, "'Enter a complete value.', 'Enter an extension.'"): | ||
| self.assertIsNone(f.clean([])) |
There was a problem hiding this comment.
Where PhoneField(required=False, ...) I'm expecting totally empty values to not raise, as per the old test.
The MVF itself is optional. If submitted, and require_all_fields=False, we defer to the individual fields to determine if they can be omitted. (That was the thought on the ticket right?)
IIUC: It looks like it's these cases here that we need to adjust. (Assuming we can do that from a BC POV.)
django/forms/boundfield.py
Outdated
| if ( | ||
| widget.use_required_attribute(self.initial) and | ||
| self.field.required and | ||
| self.form.use_required_attribute | ||
| ): | ||
| attrs["required"] = True |
There was a problem hiding this comment.
We need to factor this differently, as it's an exact duplicate of the added block above.
| try: | ||
| field_value = value[i] | ||
| except IndexError: | ||
| except (IndexError, TypeError): |
There was a problem hiding this comment.
What's the addition here for?
|
Hi @carltongibson, Let's try and agree the expected behaviour. The ticket explained that it is odd to allow a null response when a widget is required. This is true; however, just looking at the To bring this to life I think there are two valid use cases.
Whilst this satisfies the requirement from a a b c d e f [ref] a = required Appreciate your thoughts. |
|
Some further thoughts on this. Apologies, for another long post.... Whilst we still need to agree the correct behaviour (previous post) I need to find a way of managing The issues I've been struggling with is that Step 1) Set the sub widget's This works and I think is much cleaner than my previous options. (I don't think it permanently changes with widgets There is a big but... many of the tests currently fail. This is because the So my question: Is there a use case for a I think the answer to this should be no...... |
|
Hi @dcsmith1. I had a look here and left some remarks on the original ticket. Essentially, I think we can vastly reduce the scope of the changes here by not making changes to validation and only dealing with the required HTML attributes in a scenario where |
Forum discussion
Ticket