django模型 - 避免在数据库设计中可能的循环引用

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (1)
  • 关注 (0)
  • 查看 (75)

我有数据库设计和关系问题,我担心可能的循环引用。

举一个例子,杰克有他的股票药品A,B和C.药品A和B有一个active_ingredient AI1和药品C有一个active_ingredient AI2。

杰克去找医生,他给他开了AI1。对于处方对象,如果他服用药物A或B则无关紧要。

这是一个示例代码:

class ActiveIngredient(models.Model):
    ...

class Medicine(models.Model):
    quantity = models.IntegerField()
    active_ingredient = models.ForeignKey("ActiveIngredient", on_delete=models.CASCADE)

class Person(models.Model):
    ...

class PersonStock(models.Model):
    customer = models.ForeignKey("Person", on_delete=models.CASCADE)
    medicine = models.ForeignKey("Medicine", on_delete=models.CASCADE)
    expiration_date = models.DateField()

class Prescription(models.Model):
    ...
    quantity = models.IntegerField()

建立这种关系的最佳解决方案是什么?

将处方改为:

class Prescription(models.Model):
    ...
    customer = models.ForeignKey("Person", on_delete=models.CASCADE)
    active_ingredient = models.ForeignKey("ActiveIngredient", on_delete=models.CASCADE)
    quantity = models.IntegerField()

鉴于已经连接Person和Medicine的PersonStock类,我似乎对我不对。

提问于
用户回答回答于

你关注重复的信息是正确的; 数据库设计(特别是数据库规范化)的一个主要问题是避免这种情况,以消除数据不一致的可能性。

然而,在这种情况下,我认为将处方和填充物分开是更有意义的。这是两个独立的事情,在现实世界中,很有可能犯错误并提供错误的药物。虽然人们应该努力防止这样的错误,但这与在数据模型中无法表示错误的情况完全不同。

所以我的建议是在应用层验证数据,而不是在数据模型本身中构建约束。就像是:

class ActiveIngredient(models.Model):
    ...

class Medicine(models.Model):
    quantity = models.IntegerField()
    active_ingredient = models.ForeignKey("ActiveIngredient", on_delete=models.CASCADE)

class Person(models.Model):
    ...

class Prescription(models.Model):
    ...
    customer = models.ForeignKey("Person", on_delete=models.CASCADE)
    active_ingredient = models.ForeignKey("ActiveIngredient", on_delete=models.CASCADE)
    quantity = models.IntegerField()

class PersonStock(models.Model):
    prescription = models.ForeignKey("Prescription", on_delete=models.CASCADE)
    medicine = models.ForeignKey("Medicine", on_delete=models.CASCADE)
    expiration_date = models.DateField()

    # Make sure the supplied medicine is correct.
    def clean(self):
        if self.medicine.active_ingredient != self.prescription.active_ingredient:
            raise ValidationError("Wrong medicine!")

或者,您只能在PersonStock创建a时进行检查。

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励