如何在管理员中删除对象并保留父级?
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
成为原始类型,然后将其子类化以创建ProblematicGift
s 和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()
编辑:将note
从ProblematicGift
移动到Gift
。使用代理模型时,不能向子类添加任何新字段。
【讨论】:
只有一个问题,在这种情况下 ProblematicGift 是如何与 Gift 关联的? 从技术上讲,它不是“链接”的。这基本上是一个别名。ProblematicGift
设置为使用is_problematic
==True 访问Gift
s 的简单方法。它基本上仍然只是 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# 以编程方式删除“包括来自此对象父级的可继承权限”复选框