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

django模型-避免数据库设计中可能出现的循环引用,django,database,django-models,Django,Database,Django Models,我有一个数据库设计和关系问题,我担心可能的循环引用 举个例子,杰克的库存中有药物A、B和C。药物A和B含有活性成分AI1,药物C含有活性成分AI2 杰克去看医生,医生给他开了所有的处方。对于处方对象,服用A药或B药是无关紧要的 下面是一个示例代码: class ActiveIngredient(models.Model): ... class Medicine(models.Model): quantity = models.IntegerField() active_

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

举个例子,杰克的库存中有药物A、B和C。药物A和B含有活性成分AI1,药物C含有活性成分AI2

杰克去看医生,医生给他开了所有的处方。对于处方对象,服用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()

考虑到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
时进行检查。

@KevinChristopherHenry问题是医生开的是活性成分,而不是药物。PersonStock是指一个人拥有的药物,处方是指在一定时间内服用的有效成分。我的问题是对处方模型进行建模,因为我觉得与活性成分有关系是不对的,因为已经有一个人把人和药物联系起来了(通过关联,活性成分)。我是否以错误的方式看待这一点?我同意@KevinChristopherHenry下面的回答,但我要补充一点,你在这里提到的两种关系有着截然不同的目的。能够单独列出患者已订购的药物与已为其开出的活性成分是有价值的。除了错误,这还允许用户检查未填写的处方。