Django模型重写保存函数未更新m2m字段的数据库
当我从管理面板添加一个新的横幅时,我想在创建时与这个横幅关联的关键词并没有被添加到数据库里。
class Banners(models.Model):
objects = BannerManager()
banner_location = models.ManyToManyField(BannerLocation, verbose_name=_("Banner's Location"), default=None, null=True, blank=True)
keywords = models.ManyToManyField(Keywords, verbose_name=_("Banner's Related Keywords"), null=True, blank=True)
width = models.IntegerField(verbose_name=_("Banner Width"), null=False, blank=False)
height = models.IntegerField(verbose_name=_("Banner Height"), null=False, blank=False)
invocation_code = models.TextField(verbose_name=_("Banner Height"), null=False, blank=False)
is_enable = models.BooleanField(verbose_name=_("Is Enable"), default=False)
banner_updated = models.DateTimeField(auto_now=True)
banner_created = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = "Banner"
verbose_name_plural = "Banners"
ordering = ['-banner_updated', 'is_enable']
def __unicode__(self):
return "width: %s, height: %s" % (self.width, self.height)
def save(self):
is_new = False
if self.pk is None:
is_new = True
super(Banners, self).save()
if is_new == True:
keyword = Keywords.objects.get(pk=1)
self.keywords.add(keyword)
1 个回答
1
如果你的管理表单里有一个 keywords
字段,发生的事情是这样的:
- 你在管理后台点击保存你的新
Banners
实例(没有选择任何关键词) - Django 的管理模型表单会保存这个
Banners
实例 - 你重写的
save
方法会添加你的关键词 - Django 管理后台会把关键词的多对多字段设置为表单中提交的关键词(这会覆盖你在保存方法中设置的内容)
Django 之所以这样做,是因为你知道的,Banners
实例必须先保存,才能添加多对多关系。
我自己以前也在这方面绕了很多圈,玩弄 m2m_changed
信号等等……但你可能最终得到的东西只是在 Django 管理网站的某些特定情况下有效,而在其他代码中就不太合理了。
我觉得你的保存方法是有效的(可以在控制台中尝试,离开 Django 管理后台),你真正需要的是自定义管理表单的行为:
class BannersForm(forms.ModelForm):
class Meta:
model = Banners
def __init__(self, *args, **kwargs):
if kwargs.get('instance') is None:
# create new Banners
initial = kwargs.get('initial', {})
initial.update({'keywords': Keywords.objects.filter(pk=1)})
kwargs['initial'] = initial
super(BannersForm, self).__init__(*args, **kwargs)
class BannersAdmin(admin.ModelAdmin):
form = BannersForm
admin.site.register(Banners, BannersAdmin)