如何最好地构建django模型以适应场景?

时间:2015-02-23 23:00:56

标签: django django-models

我正在建模一个系统,该系统涉及使用配方中的少量输入来创建输出的过程。输入具有输出属性的子集,但复杂的是输出也可用作输入。配方需要不同数量的不同输入。理想情况下,我想这样做:

class CommonAttrs(models.Model):
    name = model.CharField()
    value = model.FloatField()
    cost = model.FloatField()

    class Meta:
        abstract = True

class Input(CommonAttrs):
    pass

class Output(CommonAttrs):
    price = model.FloatField()
    demand = model.FloatField()
    ...

class Recipe(models.Model):
    output = model.ForeignKey(Output)
    input_1 = model.OneToMany([Input, Output])  # I can dream
    quantity_1 = model.FloatField()
    input_2 = model.OneToMany([Input, Output])
    quantity_2 = model.FloatField()
    input_3 = model.OneToMany([Input, Output])
    quantity_3 = model.FloatField()
    input_4 = model.OneToMany([Input, Output])
    quantity_4 = model.FloatField()

然而,代替django中的OneToMany关系,我已经完成了:

class Recipe(models.Model):
    output = model.ForeignKey(Output)
    input = model.ManyToManyField(Input, through='Measures')

class Measures(models.Model):
    recipe = model.ForeignKey(Recipe)
    input = model.ForeignKey(Input)
    quantity = model.FloatField()

这一切都很好,但是错过了输出的关键细节,也是食谱的输入。我在我的数据库中创建了一个视图,并尝试创建一个新的非托管模型来代替Input:

class InputOrOutput(CommonAttrs):

    class Meta:
        managed = False
        db_table = 'input_union_output_view'  # Does what is says on the tin

然而,这导致了初始化和迁移问题的泥潭。

我的最后一招是创建一个完整的表而不是视图,但这感觉就像是因为数据不一致而感到头疼。

有哪些更好的选择?

2 个答案:

答案 0 :(得分:3)

假设,根据输入和输出不能放在同一个表中的注释,那么通用外键​​可能是拥有绑定到任一模型的关系的最佳选择。从食谱代码开始:

from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType

class Recipe(models.Model):
    output = model.ForeignKey(Output)
    input_1_content_type = models.ForeignKey(ContentType)
    input_1_object_id = models.PositiveIntegerField()
    input_1_content_object = GenericForeignKey('input_1_content_type', 'input_1_object_id')
    quantity_1 = model.FloatField()

这将为您的input_1提供通用FK。如果你必须手动完成每个输入,那就是很多代码,但也许没关系。

如果有一种开箱即用的通用M2M的简单方法会很好,但我不相信它。相反,也许一个中级课程可以帮助你完成大部分工作:

class Recipe(models.Model):
    output = model.ForeignKey(Output)
    @property
    def inputs(self):
        return self.recipeinput_set


class RecipeInput(models.Model):
    recipe = models.ForeignKey(Recipe)
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')
    quantity = model.FloatField()

答案 1 :(得分:1)

在不知道InputOutput是什么的情况下,我会假设它的食物。这很方便。

食谱使用食物来生产不同类型的食物。

class Recipe(models.Model):
    output = model.ForeignKey(Food, related_name="produced_by")
    input = model.ManyToManyField(Food, through='Measures')

例如(此代码可能有效,也可能无效,但说明了这一点):

cheese = Food("Cheese")
bread  = Food("Bread")
toasty = Food("Toasted Cheese Sandwich")

toasty.produced_by = Recipe(input=[cheese,bread])  

输入度量然后只引用Food项。

class Measures(models.Model):
    recipe = model.ForeignKey(Recipe)
    input = model.ForeignKey(Food)
    quantity = model.FloatField()

每个Food都有一个购买和销售价格 - 假设没有什么能阻止我购买奶酪然后再卖掉它。

class Food(models.Model):
    name = model.CharField()
    value = model.FloatField()
    purchase_price = model.FloatField()
    sale_price = model.FloatField()
    demand = model.FloatField()