gpt4 book ai didi

django - 当 commit=False 时,Django 表单 save() 方法中是否需要 save_m2m() ?

转载 作者:行者123 更新时间:2023-12-01 19:44:54 25 4
gpt4 key购买 nike

文档似乎非常坚定地表明情况确实如此......

https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#the-save-method

我特别提到了这一部分:

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.

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.

我对 django 还很陌生,昨天偶然发现了这个信息。

但是,我有一个观点,我不调用 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')

那为什么我的观点有效呢? (这意味着,表单中某一字段的 m2m 关系实际上是在处理表单时保存的。)

最佳答案

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

这是完整的method从 Django 1.4 开始:

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

所以你已经得到它了。然而,让我指出一些潜在的困惑。 @Wogan 很聪明地指出你没有保存你的对象。按照您的代码的方式,您使用未保存的模型实例进行验证,然后它被丢弃,因为 ModelFormMixin 重新分配 self.object

  1. 这意味着如果您稍后访问 self.object,它可能不是您所期望的。
  2. 您丢失了 self.object.user 信息。 (因为 user 是模型上的必填字段,并且您在表单中将其排除,所以我预计 save() 会失败。因此父级 AuthCreateView 一定在做某事。当然,它可能正在处理整个 save() 并且根本不会命中 ModelFormMixin。)

为了避免这种困惑,只需不要将您的实例分配给 self.object 即可。也许: validate_obj = form.save(commit=False)

关于django - 当 commit=False 时,Django 表单 save() 方法中是否需要 save_m2m() ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7083152/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com