我正在建模一个系统,该系统涉及使用配方中的少量输入来创建输出的过程。输入具有输出属性的子集,但复杂的是输出也可用作输入。配方需要不同数量的不同输入。理想情况下,我想这样做:
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
然而,这导致了初始化和迁移问题的泥潭。
我的最后一招是创建一个完整的表而不是视图,但这感觉就像是因为数据不一致而感到头疼。
有哪些更好的选择?
答案 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)
在不知道Input
或Output
是什么的情况下,我会假设它的食物。这很方便。
食谱使用食物来生产不同类型的食物。
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()