问题
I need to set initial data to formset with ManyToMany field.
Usually i'm doing like this when there is no ManyToMany field in forms of my fomset:
PersonFormSet = forms.formsets.formset_factory(NickName, can_delete=True)
init_data = [{'name':'Vasya pupkin','nick':'Vasya'},
{'name':'Vasyapupkin','nick':'Petya'}]
nick_formset = PersonFormSet(initial=init_data)
But now I need to set ManyToMany field initial data and tried something like this:
NickNameFormSet = forms.formsets.formset_factory(NickName, can_delete=True)
init_data = [{'name': 'Vasya Pupkin',
'nick': {'Vasya':'selected',
'Petya':'notselected'}}]
nick_formset = NickNameFormSet(initial=init_data)
But it doesn't works.
How can I pass initial data to Formset so it render my widget like this:
<select multiple="multiple" name="person_set-0-nickname" id="id_person_set-0-nickname">
<option value="1" selected="selected">Vasya</option>
<option value="2">Petya</option>
</select>
Note: I'm using only Forms, and Formsets of Django. There is no Django models. I can actually define it but it's empty, I'm using NoSQL.
回答1:
You should provide a list of pk as initial data for your ManyToMany relation instead of a dict.
Take a look at this thread, it might helps you.
回答2:
You can use the __init__ function to pre-populate initial data.
Here's what I used for a similar problem:
class MyUpdateForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(MyUpdateForm, self).__init__(*args, **kwargs)
self.initial['real_supplements'] = [s.pk for s in list(self.instance.plan_supplements.all())]
Instead of using self.instance.plan_supplements.all() in my example, you can provide any Queryset.
回答3:
Like this:
class CustomFormSet(BaseInlineFormSet):
def __init__(self, *args, **kwargs):
kwargs['initial'] = [
{'foo_id': 1}
]
super(CustomFormSet, self).__init__(*args, **kwargs)
the foo_id depends on the value that you're selecting for which field on the model relationship
You have to change also the has_changed method on the form class in order for the it to know that the initial values are "changed" to be taken in account when saved:
class CustomForm(forms.ModelForm):
def has_changed(self):
"""
Overriding this, as the initial data passed to the form does not get noticed,
and so does not get saved, unless it actually changes
"""
changed_data = super(starnpc_class, self).has_changed()
return bool(self.initial or changed_data)
来源:https://stackoverflow.com/questions/5223048/django-set-initial-data-to-formset-with-manytomany