Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I guess you would have here to add a new <code>ModelMultipleChoiceField</code> to your <code>PizzaForm</code>, and manually link that form field with the model field, as Django won't do that automatically for you.</p> <p>The following snippet might be helpful :</p> <pre><code>class PizzaForm(forms.ModelForm): class Meta: model = Pizza # Representing the many to many related field in Pizza toppings = forms.ModelMultipleChoiceField(queryset=Topping.objects.all()) # Overriding __init__ here allows us to provide initial # data for 'toppings' field def __init__(self, *args, **kwargs): # Only in case we build the form from an instance # (otherwise, 'toppings' list should be empty) if kwargs.get('instance'): # We get the 'initial' keyword argument or initialize it # as a dict if it didn't exist. initial = kwargs.setdefault('initial', {}) # The widget for a ModelMultipleChoiceField expects # a list of primary key for the selected data. initial['toppings'] = [t.pk for t in kwargs['instance'].topping_set.all()] forms.ModelForm.__init__(self, *args, **kwargs) # Overriding save allows us to process the value of 'toppings' field def save(self, commit=True): # Get the unsave Pizza instance instance = forms.ModelForm.save(self, False) # Prepare a 'save_m2m' method for the form, old_save_m2m = self.save_m2m def save_m2m(): old_save_m2m() # This is where we actually link the pizza with toppings instance.topping_set.clear() instance.topping_set.add(*self.cleaned_data['toppings']) self.save_m2m = save_m2m # Do we need to save all changes now? if commit: instance.save() self.save_m2m() return instance </code></pre> <p>This <code>PizzaForm</code> can then be used everywhere, even in the admin :</p> <pre><code># yourapp/admin.py from django.contrib.admin import site, ModelAdmin from yourapp.models import Pizza from yourapp.forms import PizzaForm class PizzaAdmin(ModelAdmin): form = PizzaForm site.register(Pizza, PizzaAdmin) </code></pre> <h3>Note</h3> <p>The <code>save()</code> method might be a bit too verbose, but you can simplify it if you don't need to support the <code>commit=False</code> situation, it will then be like that :</p> <pre><code>def save(self): instance = forms.ModelForm.save(self) instance.topping_set.clear() instance.topping_set.add(*self.cleaned_data['toppings']) return instance </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload