文档似乎很确定确实如此。
https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#the-save-method
我特指此部分:

我对django很陌生,昨天偶然发现了这些信息。
但是,我有一个 View ,在这里我不调用save_m2m()方法,但实际上保存了m2m数据。
这是我的看法:

class SubscriberCreateView(AuthCreateView):
    model = Subscriber
    template_name = "forms/app.html"
    form_class = SubscriberForm
    success_url = "/app/subscribers/"

    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["email"] = ErrorList([u"This subscriber email is already in your account."])
            return super(SubscriberCreateView, self).form_invalid(form)
        return super(SubscriberCreateView, self).form_valid(form)
我的模特:
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
我的表格:
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')
那么,为什么我的 View 起作用? (这意味着,在处理表单时,实际上保存了表单中字段之一的m2m关系。)

最佳答案

父类之一正在执行模型对象及其m2m关系的完整保存。我不确定,因为我没有AuthCreateView的声明,但是命名约定表明它起源于“CreateView”。如果是这样,则View的继承就是SubscriberCreateView -> AuthCreateView -> CreateView -> BaseCreateView -> ModelFormMixin。 ModelFormMixin具有 form_valid() 方法,您(可能)使用调用super()

这是Django 1.4中的整个method:

def form_valid(self, form):
    self.object = form.save()
    return super(ModelFormMixin, self).form_valid(form)

所以你有它。但是,让我指出一些潜在的困惑。当指出您不保存对象时,@ Wogan非常聪明。按照代码的方式,您可以使用未保存的模型实例进行验证,然后将其丢弃,因为ModelFormMixin重新分配了self.object
  • 这意味着self.object可能与以后访问时所期望的不一样。
  • 您丢失了self.object.user信息。 (因为user是模型上的必填字段,并且您将其排除在表单中,所以我希望save()失败。因此父AuthCreateView必须正在执行某些操作。 。)

  • 为了避免这种困惑,只需不将实例分配给save()即可。也许:ModelFormMixin

    10-04 15:40