Django OneToOne 字段到自我
Posted
技术标签:
【中文标题】Django OneToOne 字段到自我【英文标题】:Django OneToOne field to self 【发布时间】:2016-11-10 16:44:07 【问题描述】:如何定义OneToOne
与同一个Model
的关系?
我有一个名为Order
的模型,它可以与另一个模型Order
配对。现在我试图弄清楚如何处理这种关系的模型。
我的想法:
class Order(models.Model):
paired_order = models.OneToOneField(self)
或者:
class Pairing(models.Model):
order1 = models.ForeignKey(Order, related_name='pairing')
order2 = models.ForeignKey(Order, related_name='pairing')
你怎么看?哪个更有效率?
我想简单地调用配对的。所以我会做这样的事情:
order.paired_order
或者:
order.pairing.paired
我希望这种关系是对称的,所以对于每一对订单我都调用相同的东西并得到成对的订单。
配对模型将是一个很好的解决方案,因为我可以为这种关系添加额外的信息,但是有一个问题是我必须检测它是哪个顺序,所以我不能打电话给order.pairing.order1
,因为我没有知道我是否没有调用相同的命令。
编辑:
>>> from _app import models
>>> order1 = models.Order(flight_number="xxx")
>>> order2 = models.Order(flight_number="yyy", paired_order=order1)
>>> order1.paired_order.flight_number
返回None object has not ....
问题是,当我将 order1 设置为 order2 的配对订单时,我想要相反方向的相同东西。所以order1.paired_order = order2
也这样做order2.paired_order = order1
。
【问题讨论】:
你在这里问什么?如何定义关系或哪个更好? Django self-referential relationship?的可能重复 Django-model: how to reference to self?的可能重复 Django self-referential foreign key的可能重复 为什么它与任何其他一对一关系的工作方式不同?您应该尝试使用这些重复项中的任何一个 【参考方案1】:我自己也有这个问题,“对称”这个词是找到答案的关键:https://code.djangoproject.com/ticket/7689
class Order(models.Model):
paired_order = models.OneToOneField(self)
def save(self, *args, **kwargs):
super(Order, self).save(*args, **kwargs)
self.paired_order.paired_order = self
super(Order, self.paired_order).save()
【讨论】:
【参考方案2】:配对模型将是一个很好的解决方案,因为我可以添加额外的 这种关系的信息。
在这种情况下,您可以为该组“订单”(您称之为配对)建模并添加一个快捷方式来检索配对订单。
class OrderPair(models.Model):
pass
# additional information goes here
class Order(models.Model):
pair = models.ForeignKey(to="OrderPair", related_name="orders")
# you'll have to add custom validation
# to make sure that only 2 orders can belong to the same "OrderPair"
@property
def paired_order(self):
return self.pair.orders.exclude(id=self.id).first()
完成此操作后,您可能还希望缓存配对订单以避免过多的查询。在这种情况下,您不需要相关名称,因此您可以使用 +
(Django 中不太明确的东西)。
class Order(models.Model):
...
cached_paired_order = models.ForeignKey(to='self', related_name='+')
@property
def paired_order(self):
if self.cached_paired_order:
...
else:
...
【讨论】:
【参考方案3】:ForeignKey
不仅接受一个类作为参数,还接受 ForeignKey('ModelNameInSameModelsPyFile')
或 ForeignKey('app_name.ModelName
形式的字符串名称。
在你的情况下,它可能是这样的
class Order(models.Model):
paired = models.ForeignKey('Order', null=True)
您可以在https://docs.djangoproject.com/en/1.8/ref/models/fields/#foreignkey阅读更多内容
【讨论】:
或者直接使用"self"
。
好的,让我们有 order1 和 order2。现在当我做 order1.paired = order2 时,我可以这样调用 order1:order2.paired 吗?可能不是,这就是问题所在。
你可以有一个related_name
,但我相信你不能叫它paired
——你需要另一个名字。
视情况而定。如果配对是唯一的,即:一个订单只能与另一个订单配对,您可以使用OneToOneField
(docs.djangoproject.com/en/1.8/ref/models/fields/#onetoonefield)。并且您需要设置related_name
(但它不能是paired
,可能是paired_to
)。如果它不是唯一的,那么它可以被order2.<related_name>.filter(....)
使用
它必须是独一无二的。一个订单有一个配对订单,反之亦然。以上是关于Django OneToOne 字段到自我的主要内容,如果未能解决你的问题,请参考以下文章
ForeignKey vs OneToOne 字段 django [重复]
Django中的OnetoOne(primary_key = Tue)到ForeignKey
如何在 Django Admin 中更改 OneToOne 模型字段默认消息?
附加“_id”的OneToOne字段上的Django过滤器并失败