通过OneToOneField自定义删除模型和关联模型

时间:2012-02-28 20:47:42

标签: django django-admin

我正在覆盖Django的delete_selected管理员行动。我有一个模型(Person)通过OneToOneField与另一个模型(Party)相关联,而delete_selected只删除原始模型,而不删除相关模型中的数据,让我“鬼行“在我的数据库中。看起来这样本身可能表明我的代码存在问题,因为我的假设是delete()函数会级联删除相关模型。

无论如何,问题是,我的自定义delete()函数首先删除Party,然后Person的OneToOneField为空并抛出错误。想法?

这是我的模特:

class Party(models.Model):
    name = models.CharField(max_length=100)
    ...

class Person(models.Model):
    party = models.OneToOneField(Party, editable=False)
    firstName=models.CharField(max_length=60)
    lastName=models.CharField(max_length=60)

    def delete(self):
        self.party.delete()
        self.delete()

我的管理员:

class PersonAdmin(admin.ModelAdmin):
    actions=['really_delete_selected']

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

    def really_delete_selected(self, request, queryset):
        for obj in queryset:
            obj.delete()

        if queryset.count() == 1:
            message_bit = "1 person was"
        else:
            message_bit = "%s people were" % queryset.count()
        self.message_user(request, "%s successfully deleted." % message_bit)
    really_delete_selected.short_description = "Delete selected entries"
    ...

错误:

AssertionError at /admin/common/person/ 
Party object can't be deleted because its id attribute is set to None.

2 个答案:

答案 0 :(得分:1)

我不确定为什么会这样,但它确实......

我将模型的delete()功能更改为:

def delete(self):
    d = self.party.id
    Party.objects.get(id__exact=d).delete()

我想这实际上是在做@Furbeenator所建议的,因为通过删除Party中的正确行,cascad也删除了Person中的正确行。在黑暗中随机拍摄的三种欢呼有时会起作用,嗯?

答案 1 :(得分:0)

Python使用缩进进行语义分析。您的def delete(self):未正确缩进,因此它不会覆盖本机delete()方法。它应该在Person的缩进级别之下。像这样:

class Party(models.Model):
    name = models.CharField(max_length=100)
    ...

class Person(models.Model):
    party = models.OneToOneField(Party, editable=False)
    firstName=models.CharField(max_length=60)
    lastName=models.CharField(max_length=60)

    def delete(self):
        self.party.delete()
        self.delete()

您的管理部分也是如此,它应该缩进为:

class PersonAdmin(admin.ModelAdmin):
    actions=['really_delete_selected']

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

    def really_delete_selected(self, request, queryset):
        for obj in queryset:
            obj.delete()

        if queryset.count() == 1:
            message_bit = "1 person was"
        else:
            message_bit = "%s people were" % queryset.count()

        self.message_user(request, "%s successfully deleted." % message_bit)
        really_delete_selected.short_description = "Delete selected entries"
        ...