覆盖delete_selected()并更新子模型的字段

时间:2012-05-30 11:02:54

标签: django model

我正在尝试覆盖名为Invoice的模型的delete方法。 Model Invoice在模型Action中由ForeignKey引用。我想更新名为“模拟管理员”的布尔字段,当它的“发票被删除”

这篇文章中描述的解决方案:

How do I override delete() on a model and have it still work with related deletes

答案是: https://stackoverflow.com/a/1539182

在model.py中

对我不起作用:

def delete(self):
      Action.objects.filter(invoice=self).update(billed=False) # and tried 0 instead of False
      super(Invoice,self).delete()

也尝试过:

def delete(self):
     actions = Action.objects.filter(invoice=self)
     for action in actions:
        action.billed=False   # and tried 0 instead of False
        action.save()
     super(Invoice,self).delete()

模型操作中的ForeignKey字段具有on_delete = models.SET_NULL,以避免在删除发票时删除操作。但我还需要将结账设置为False。

invoice = models.ForeignKey( Invoice, verbose_name = 'Rechnung', null=True, blank=True,on_delete=models.SET_NULL)

我刚刚在这里阅读https://code.djangoproject.com/ticket/10751,在管理员中,所选的操作删除无法使用delete()覆盖

我必须使用delete_view()

所以我试过

def delete_selected(self, request, obj, extra_context=None):
    Action.objects.filter(invoice=self).update(billed=False)
    super(InvoiceAdmin, self).delete_view(request, obj, extra_context)

还尝试使用obj而不是self,但不是解决方案

2 个答案:

答案 0 :(得分:7)

我找到了一个解决方案,发表了Stephane https://stackoverflow.com/a/4534773/326905,并根据我的问题对其进行了编辑。

正确的操作是 delete_selected 在InvoiceAdmin模型下的 admin.py

actions = ['delete_model']

def get_actions(self, request):
    actions = super(InvoiceAdmin, self).get_actions(request)
    del actions['delete_selected']
    return actions

def delete_model(self, request, obj):
    for o in obj.all():
        Action.objects.filter(invoice=o).update(billed=False)
        o.delete()

delete_model.short_description = 'Ausgewählte Rechnungen löschen'

答案 1 :(得分:7)

虽然this answer有效,但如果您在代码中的任何其他地方删除了一个obj,则delete_model方法会抛出错误。

我推荐这个:

actions = ['delete_selected']

def delete_selected(self, request, obj):
    for o in obj.all():
        Action.objects.filter(invoice=o).update(billed=False)
        o.delete()

delete_selected.short_description = 'Ausgewählte Rechnungen löschen'

只需覆盖“更改列表”管理页面的delete_selected操作即可。这样您就不必完全删除操作,覆盖delete_model方法,而且您还可以从更改<object>管理页面中删除单个项目。从长远来看,它的代码较少。 :)