不为ForeignKey('self')

时间:2009-07-02 23:07:05

标签: django django-models

如何让ForeignKey返回对象本身?我在尝试:

Alias(MyBaseModel):
    type = models.ForeignKey('self')

a = Alias()
a.type = a
a.save()

但是当我运行它时:

(1048, "Column 'type_id' cannot be null")

我不希望该类型为null,我希望它包含自己的ID。我有大量的对象,但只有一个循环回到自身,所以我真的不想让它为空。想法?

3 个答案:

答案 0 :(得分:4)

问题是当你执行a.type = a时,数据库中还没有a,因此它没有pk。

解决此问题的一种方法是保存两次,首先将其保存到数据库中,引用已存在于数据库中的虚拟对象,然后一旦从数据库中获取它就再次保存。这样做的一个问题是,实际上首先将这样的对象放入数据库中存在鸡和蛋的问题。我通过在每次使用sync-db时创建一个夹具来处理这个问题,这样就有一个这样的对象存在且有效。

另一种选择是放宽非空约束并且努力分配它们。

无论哪种方式,插入这样的表总是会很痛苦,因为你不能在没有第一次插入的情况下使用PK,并且无论在ORM中如何都不能在没有密钥的情况下插入参考字段或数据库或任何东西。

另一种解决方案是打破循环依赖,并执行以下操作:

AliasType(django.db.Model):
    pass

Alias(MyBaseModel):
    type = models.ForeignKey(AliasType)

a = Alias()
a_t = AliasType()
a_t.save()
a.type = a_t
a.save()

您仍然可以使用django非常智能的访问器获取有用的信息,

AliasType.objects.all()[0].alias_set

可以让你回到原始的Alias对象而没有明确的链接。

答案 1 :(得分:1)

你的类型字段不应该是 null = True,blank = True ?否则你的基本案例是什么? 我的意思是如果你在db中只有一个对象是什么类型的?

通过采用空类型字段意味着 - 该对象引用自身的约定,可以克服对象循环自身的问题!

如果类型字段不为空,则表示它引用了另一个Alias对象,该对象只是极好的。

您的问题在算法级别没有意义(除非我遗漏了某些内容),那么如何才能让它在db中运行?

Alias(MyBaseModel):
    type = models.ForeignKey('self', blank=True, null=True)

a = Alias()
a.save()
# Now a refers to itself

b = Alias()
b.type = a
b.save()
# b does not refer to itself, but rather a

我知道我稍微重新定义了这个问题,很抱歉,如果那不是你想要的那个!欢呼声。

答案 2 :(得分:0)

set null=true , blank=true in your code
like,

Alias(MyBaseModel):
    type = models.ForeignKey('self' , blank=True, null=True)

a = Alias()
a.type = a
a.save()