如何在管理员中删除对象并保留父级?

Posted

技术标签:

【中文标题】如何在管理员中删除对象并保留父级?【英文标题】:How to delete object in admin and keep parent? 【发布时间】:2011-09-11 22:29:54 【问题描述】:

我有以下问题:

class Gift(models.Model):                                            
    name        = models.CharField(max_length=255,default='')

class ProblematicGift(Gift):
    # it does not help  gift_ptr = models.OneToOneField(Gift, parent_link=True, default=None, null=True, blank=True, on_delete=models.DO_NOTHING)
    notes       = models.CharField(max_length=255,default='')

如何在管理界面删除 ProblematicGift 的对象并保留 Gift 的对象?

简化背景:自动选择有问题的礼物并将其添加到表格中,管理员查看它,修复礼物并删除有问题的礼物

【问题讨论】:

【参考方案1】:

你有三个选择:

    最快最简单的方法是在ProblematicGift 的基础上创建一个新的Gift,然后删除ProblematicGift

    您可以使用抽象继承使Gift 成为原始类型,然后将其子类化以创建ProblematicGifts 和GoodGifts 之类的东西。之后的过程几乎相同:它们每个都有单独的表,所以你添加一个GoodGift,然后删除ProblematicGift。它与 #1 几乎相同,但更具语义性。

    可能是您的最佳选择:使用代理模型。您将布尔属性添加到诸如“is_problematic”之类的形式的礼物中。然后,创建ProblematicGift 作为Gift 的代理,在创建时自动将is_problematic 设置为True,并覆盖经理以仅返回is_problematic 设置为True 的礼物。然后,您只需将该属性设置为 False,而不是删除 ProblematicGift,它就会离开查询集。

--

class Gift(models.Model):
    name           = models.CharField(max_length=255,default='')
    notes          = models.CharField(max_length=255,default='')
    is_problematic = models.BooleanField(default=False)

class ProblematicGiftManager(models.Manager):
    def get_query_set(self, *args, **kwargs):
        qs = super(ProblematicGiftManager, self).get_query_set(*args, **kwargs)
        return qs.filter(is_problematic=True)

class ProblematicGift(models.Model):

    objects        = ProblematicGiftManager()

    class Meta:
        proxy = True

    def save(self, *args, **kwargs):
        # Make sure it's new
        if not self.pk: 
            self.is_problematic = True

        super(ProblematicGift, self).save(*args, **kwargs)

    def resolve(self):
        self.is_problematic = False
        self.save()

编辑:noteProblematicGift 移动到Gift。使用代理模型时,不能向子类添加任何新字段。

【讨论】:

只有一个问题,在这种情况下 ProblematicGift 是如何与 Gift 关联的? 从技术上讲,它不是“链接”的。这基本上是一个别名。 ProblematicGift 设置为使用is_problematic==True 访问Gifts 的简单方法。它基本上仍然只是 Gift 伪装成不同的对象。 是的,我明白 :),但我不知道如何根据礼物进行查询。在管理器中从 ProblematicGift 进行查询。我尝试 make meta.proxy=true 并继承,但我不能使用字段注释(这是可以理解的:-/) 是的,对不起,那是因为我匆忙的复制粘贴工作。您仍然可以使用note,但您必须将其移至Gift。由于代理模型没有自己的表,它们不能添加额外的字段。 没关系 :) 问题在于“注释”,它必须留在有问题的礼物中,因为它是关于问题的注释,应该在解决后删除。注意:在这种情况下应该可以使用 django 中的错误:) 因为当您从代理模型继承时,父级不会被删除,但我已经报告了错误..【参考方案2】:

老实说,您所犯的错误是试图从Gift 继承。您不想为您的用例这样做。

最好的办法是让Gift成为一个独立的模型:

class Gift(models.Model):                                            
    name = models.CharField(max_length=255,default='')

然后让 ProblematicGift 引用它:

class ProblematicGift(models.Model):
    gift = models.OneToOneField(Gift, null=True, blank=True)
    notes = models.CharField(max_length=255,default='')

    # this method added based on a comment
    def __unicode__(self):
        return self.gift.name

现在您可以安全地删除 ProblematicGift。

【讨论】:

是的,我以前有过,但是使用此代码,我没有直接在管理页面中看到礼物名称。只有对象的链接,在大量的记录中很难找到合适的礼物。 所以定义一个__unicode__函数。它甚至可以是return unicode(self.gift) 有没有办法在管理页面中编辑这个“名称”以获得有问题的礼物?

以上是关于如何在管理员中删除对象并保留父级?的主要内容,如果未能解决你的问题,请参考以下文章

django admin 在 save_model 方法中删除内联对象

如何删除列表中重复的构造对象,同时保留顺序并在飞镖中返回列表?

复制 OS 磁盘后如何在 Azure ASM 中保留/设置默认管理员密码

使用 C# 以编程方式删除“包括来自此对象父级的可继承权限”复选框

QSystemTrayIcon in 4.8 - 如何删除这个东西?

在 MATLAB 中删除对象句柄并保留变量