title: Is save_m2m() required in the Django forms save() method when commit=False?
body: <p>The docs seem pretty firm that this is indeed the case....</p>
  <p><a href="https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#the-save-method" rel="noreferrer">https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#the-save-method</a></p>
  <p>And I specifically refer to this section:</p>
  <blockquote>
  <p>Another side effect of using commit=False is seen when your model has a many-to-many relation with another model. If your model has a many-to-many relation and you specify commit=False when you save a form, Django cannot immediately save the form data for the many-to-many relation. This is because it isn't possible to save many-to-many data for an instance until the instance exists in the database.</p>
  <p>To work around this problem, every time you save a form using commit=False, Django adds a save_m2m() method to your ModelForm subclass. After you've manually saved the instance produced by the form, you can invoke save_m2m() to save the many-to-many form data.</p>
  </blockquote>
  <p>I am pretty new to django and stumbled upon this information yesterday.</p>
  <p>However, I have a view where I do not invoke the save_m2m() method but it does in fact save the m2m data.</p>
  <p>Here is my view:</p>
  <pre><code>class SubscriberCreateView(AuthCreateView):
      model = Subscriber
      template_name = &quot;forms/app.html&quot;
      form_class = SubscriberForm
      success_url = &quot;/app/subscribers/&quot;
  
      def get_form_kwargs(self):
          kwargs = super(SubscriberCreateView, self).get_form_kwargs()
          kwargs.update({'user': self.request.user})
          return kwargs
  
      def form_valid(self, form):
          self.object = form.save(commit=False)
          self.object.user = self.request.user
          try:
              self.object.full_clean()
          except ValidationError:
              form._errors[&quot;email&quot;] = ErrorList([u&quot;This subscriber email is already in your account.&quot;])
              return super(SubscriberCreateView, self).form_invalid(form)
          return super(SubscriberCreateView, self).form_valid(form)
  </code></pre>
  <p>My model:</p>
  <pre><code>class Subscriber(models.Model):
  
      STATUS_CHOICES = (
          (1, ('Subscribed')),
          (2, ('Unsubscribed')),
          (3, ('Marked as Spam')),
          (4, ('Bounced')),
          (5, ('Blocked')),
          (6, ('Disabled')),
      )
  
      user = models.ForeignKey(User)
      status = models.IntegerField(('status'), choices=STATUS_CHOICES, default=1)
      email = models.EmailField()
      subscriber_list = models.ManyToManyField('SubscriberList')
      first_name = models.CharField(max_length=70, blank=True)
      last_name = models.CharField(max_length=70, blank=True)
      phone = models.CharField(max_length=20, blank=True)
      facebook_id = models.CharField(max_length=40, blank=True)
      twitter_id = models.CharField(max_length=40, blank=True)
      address1 = models.CharField(max_length=100, blank=True)
      address2 = models.CharField(max_length=100, blank=True)
      postcode = models.CharField(max_length=10, blank=True)
      city = models.CharField(max_length=30, blank=True)
      country = models.CharField(max_length=30, blank=True)
      date_joined = models.DateTimeField(auto_now_add=True)
      date_updated = models.DateTimeField(auto_now=True)
  
      class Meta:
          unique_together = (
              ('user', 'email',),
          )
      
      def __unicode__(self):
          return self.email
  </code></pre>
  <p>My form:</p>
  <pre><code>class SubscriberForm(ModelForm):
      def __init__(self, user, *args, **kwargs):
          super (SubscriberForm, self).__init__(*args, **kwargs)
          self.fields['subscriber_list'].queryset = SubscriberList.objects.filter(user=user)
      
      class Meta:
          model = Subscriber
          exclude = ('user', 'facebook_id', 'twitter_id')
  </code></pre>
  <p>Why does my view work, then? (meaning, the m2m relation of one of the fields in the form is in fact saved when the form is processed.)</p>