有很多地方建议将ForeignKey
用于一对多或多对一的关系,但我很难理解如何在没有逆转依赖的情况下实现这一点。
例如:
我有这2个应用,'和解'和付款'理想情况下,和解协议不需要了解付款,因为付款记录是在结算后创建的,而付款记录可能包含多个和解。
和解模式:
class Settlement(models.Model):
...
付款模式:
class Payment(models.Model):
settlements = models.ManyToManyField('Settlement')
....
这带来了基本的模式警告,即结算可以属于多次付款,这不应该发生。
要强制执行结算不能属于多个付款记录,我必须将付款foreignkey
放入结算中:
和解模式:
class Settlement(models.Model):
payment = models.ForeignKey('Payment')
...
付款模式:
class Payment(models.Model):
....
虽然这会强制执行架构有效性,但似乎依赖性已经逆转,现在解决方案需要了解付款,只是让这两个应用程序紧密耦合。此外,我需要创建一个结算记录,其中付款字段为空,创建付款记录,然后返回到结算记录以链接付款记录,这似乎是错误的。
答案 0 :(得分:2)
虽然在Settlement
上有一个链接到Payment
的外键可能有意义,但您的应用程序不必具有该关系(或在数据库上强制执行) 。我将假设Settlement
无法更改,并且您只能使用Payment
应用。
只需创建您自己的中间模型/表格,然后将 与付款相关联即可。它就像拥有ManyToMany关系,但你可以强制执行约束。
class Payment(models.Model):
# your fields go here
class Invoice(models.Model):
settlement = models.OneToOneField('settlements.Settlement')
payment = models.ForeignKey(Payment)
请注意OneToOneField
。这基本上是具有唯一约束的外键。我们正在模拟ManyToMany中间表,但将settlement
限制为只在发票表中包含一条记录。
我应该注意,因为我们在这里创建了一个新表,由于需要额外的连接,未来的查询可能会很慢。如果您修改Settlement
模型以包含ForeignKey,它将从标准化意义上执行并且看起来更好。
答案 1 :(得分:1)