【问题标题】: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 的对象?

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

【问题讨论】:

    标签: django model admin parent


    【解决方案1】:

    你有三个选择:

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

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

    3. 可能是您的最佳选择:使用代理模型。您将布尔属性添加到诸如“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)
    • 有没有办法在管理页面中编辑这个“名称”以获得有问题的礼物?
    猜你喜欢
    • 2016-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-06
    • 2018-07-20
    • 1970-01-01
    • 2022-06-28
    • 1970-01-01
    相关资源
    最近更新 更多