Django模型覆盖保存功能,不更新db中的m2m字段 [英] Django model override save function not updating m2m field in db

查看:196
本文介绍了Django模型覆盖保存功能,不更新db中的m2m字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我从管理面板中添加一个新的横幅时,我想在其创建时关联横幅的关键字不会添加到db中。

  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 Keyword),null = True,blank = True)
width = models.IntegerField(verbose_name = _ (横幅宽度),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):
returnwidth:%s,height:%s%(self.width,self.height)

def save(self):
is_new = False
如果self.pk为无:
is_new = True
超级(横幅,自身).save()
如果is_new == True:
keyword =关键字.objects.get(pk = 1)
self.keywords.add(关键字)


解决方案

如果您的管理员表格中有关键字字段,则会发生什么:


  1. 您按保存在您的新的横幅实例在管理员(没有选择关键字)

  2. Django admin model-form保存横幅实例

  3. 您被覆盖的保存方法添加你的keyw ords

  4. Django管理员将关键字m2m字段设置为表单中提交的任何关键字(替换您在保存方法中设置的内容)

Django执行此操作的原因是因为您知道,必须先保存横幅实例,然后才能添加m2m关系。 / p>

我过去一直在圆圈,自己在过去搞乱了$ code> m2m_changed 信号等等,可能最终只能在Django管理员网站的狭窄环境中工作,但在其他代码中没有任何意义。



您的保存方法是工作我认为(在Django管理员外部的控制台中尝试),您真正需要的是自定义管理表单的行为:

  class BannersForm(forms.ModelForm):
class Meta:
model =横幅

def __init __(self,* args,** kwargs):
if kwargs.get('instance')为无:
#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(横幅,BannersAdmin)


When I add a new Banner from admin panel the keyword I want to associate with the banner at its creation does not get added in db.

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)

解决方案

If you have the keywords field in your admin form what happens is this:

  1. you press save on your new Banners instance in the admin (with no keywords selected)
  2. Django admin model-form saves the Banners instance
  3. your overridden save method adds your keywords
  4. Django admin sets the keywords m2m field to whatever keywords were submitted in the form (replacing what you set in the save method)

The reason Django does this is because, as you know, the Banners instance has to be saved before m2m relations can be added.

I have been round in circles with this myself in the past messing with m2m_changed signal etc... but you're likely to end up with something that only works in narrow set of circumstances in the Django admin site, but doesn't make sense in other code.

Your save method is working I think (try it in a console, outside Django admin), what you really need is to customise behaviour of the admin form:

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)

这篇关于Django模型覆盖保存功能,不更新db中的m2m字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆