如何解决models.ForeignKey 是否接受自身的实例作为默认值?
class Foo(models.Model):
b = models.CharField(max_length=10)
parent = models.ForeignKey('self',on_delete=models.CASCADE)
这个 Foo.parent 默认值应该是同一个实例。 我的意思是如果用户没有指定父字段,它需要引用正在创建的对象。
我该如何实施?
解决方法
默认情况下您不能引用对象本身。这样做的主要问题之一是,即使您可以设置 item.parent = item
,如果您将其保存到数据库中,item.parent
也会出现问题,因为那时 {{ 1}} 还没有主键。
您可以做的是覆盖 item
的 create(…)
方法,让它处理大部分逻辑。因此我们定义了一个 QuerySet
的子类:
QuerySet
然后在模型中我们使字段可以为空并默认设置为class TreeQuerySet(QuerySet):
def create(self,*args,**kwargs):
item = super().create(*args,**kwargs)
if item.parent is None:
item.parent_id = item.pk
return super().create(*args,**kwargs)
return item
:
None
然后您可以创建这样的 class Foo(models.Model):
b = models.CharField(max_length=10)
parent = models.ForeignKey(
'self',null=True,on_delete=models.CASCADE,default=None
)
objects = TreeQuerySet.as_manager()
对象:
Foo
以不同的方式创建 # no parent specified ↓
Foo.objects.create(b='foobar')
对象是行不通的。
话虽如此,如果不再有父项,您最好将该字段设置为 Foo
,这也将避免陷入无限循环。它还简化了建模,因为 None
可以用作默认值。
您也可以将 None
/NULL
存储在对象中,但使用将引用节点的属性,以防父节点没有其他父节点,例如:
None
然后使用 class Foo(models.Model):
b = models.CharField(max_length=10)
parent = models.ForeignKey(
'self',default=None
)
@property
def parent_or_self(self):
if self.parent is not None:
return self.parent
return self
,尽管我不相信这比仅使用 item.parent_or_self
/None
更好。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。