Opened 10 years ago
Closed 10 years ago
#24453 closed Bug (invalid)
Initial values for ManyToMany form fields can't be hidden
Reported by: | girzel | Owned by: | nobody |
---|---|---|---|
Component: | Forms | Version: | 1.7 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Initial values can be provided for the ManyToMany field of a ModelForm, to be used in a ModelFormSet, but if the widget is switched to the HiddenInput class, the (as far as I can tell correct) initial value creates a validation error:
(Hidden field <field_name>) Enter a list of values.
Take this model:
class Work(models.Model): authors = models.ManyToManyField(Author) initial = dict(authors=[some_author_instance]) formset = WorkFormSet(queryset=Work.objects.none(), initial=[initial])
This is supposing one extra form in the formset. If the "authors" field remains unhidden, the initial value works as expected. If we switch the "authors" widget to a forms.HiddenInput, however, I get the above validation error.
I don't think simply hiding the input should affect how the initial values are treated. FWIW, here's an example what the hidden input looks like in the HTML:
<input id="id_form-1-authors" name="form-1-authors" type="hidden" value="[37L]" />
So presumably "[37L]" isn't getting read as a list, somewhere...
Change History (5)
comment:2 by , 10 years ago
Thanks for the response! I previously tried it with a list of pks instead of instances, and it behaves exactly the same way (the value shows up in the HTML as "[37L]" in both cases), with the same error. I'm constructing a list of field names to be hidden, and putting them in a variable called "hidden", and then:
WorkFormSet = modelformset_factory(Work, widgets=dict([(f, forms.HiddenInput()) for f in hidden]),)
That's how I hide them. It works correctly for any field that isn't a ManyToManyField.
Should I be hiding this field some other way?
comment:3 by , 10 years ago
Ahh... I think you want to use a MultipleHiddenInput. Cause, you know, apparently that exists :)
https://docs.djangoproject.com/en/1.7/ref/forms/widgets/#composite-widgets
I wonder if there's a good place to document your situation so other people don't run into the same thing. Or if it would be safe to make HiddenInput() error when given a list.
comment:4 by , 10 years ago
I had no idea! It works perfectly. Consider this a documentation bug report, then. :)
First, it might be nice to note this requirement here:
https://docs.djangoproject.com/en/1.7/ref/forms/fields/#django.forms.ModelMultipleChoiceField
And just say that, if you want to hide the input, you have to use MultipleHiddenInput. Second, the HiddenInput widget documentation (which I did look at) says this:
Note that there also is a MultipleHiddenInput widget that encapsulates a set of hidden input elements.
"A set of hidden input elements" is not at all how I was thinking of a ManyToManyField. Perhaps something like "that is used to hide inputs that return multiple values". Or, "that return a list of values". Or...
What would probably be nicest is to have a way to say fields["authors"].hidden = True
, and let Django figure it out. That would be a much larger project, however.
Also I found this intriguing, though incomprehensible:
Thanks very much for your help.
comment:5 by , 10 years ago
Resolution: | → invalid |
---|---|
Status: | new → closed |
Hi, I think the initial is expecting integers/long instead of instances. When I pass in an
instance
and call as_hidden() I get multiple hidden inputs as expected.Though I also didn't try with a formset. How are you making it hidden?