假设我们在Django中发布了这样的表格:
rate=10
items= [23,12,31,52,83,34]
项目是Item模型的主键。我有一堆业务逻辑,它将根据这些数据运行并创建更多项目,一些数据库查找的结果和一些业务逻辑。我想将该逻辑放入保存信号或另一个模型的重写Model.save()
方法(让我们称之为Inventory
)。当我使用此表单数据创建新的Inventory
对象时,将运行业务逻辑。库存将如下所示:
class Inventory(models.Model):
picked_items = models.ManyToManyField(Item, related_name="items_picked_set")
calculated_items = models.ManyToManyField(Item, related_name="items_calculated_set")
rate = models.DecimalField()
... other fields here ...
将根据传入的项目创建新的calculated_items
,这些项目将存储为picked_items
。
我的问题是:这个模型上的save()
方法更适合接受:
我知道这有点主观,但我想知道一般的想法是什么。我查看过很多代码,但是我很难找到自己喜欢的模式。
澄清:
好的,所以共识是它应该在模型上进入不同的功能,例如inventory.calculate(...)
,然后创建所有内容,执行业务逻辑等......这很有用。我的问题仍然是:将表单数据查找到db对象的最佳位置在哪里?此函数的调用者是否应将主键转换为数据库模型,或者模型方法是否应接受主键并自行执行?这是我想在整个项目范围内做同样的事情。
澄清2:
好的,现在对于覆盖save
是否合适存在一些分歧。
当您获得简单CRUD类型操作的表单提交时,您将模型和值作为参数传递给Model.objects.create(...)
或覆盖save
或使用信号或其他任何内容。
我认为我的问题的核心是:
如果表单提交具有用于业务逻辑的相关模型,那么您需要将一些业务逻辑写入模型层。当你这样做,它应该去哪里,该方法应该接受一个对象列表或一个id的列表?模型API应该接受对象还是id?
答案 0 :(得分:1)
好的,所以我得到的前两个答案现在已经与其他人相矛盾了。我一直在研究这个问题,我打算自己回答一下。如果您认为这是正确的,请投票和/或如果您不同意我的推理,请发表评论。
模型上的方法应该接受对象和对象列表,而不是id作为int / long或id的列表或类似的东西。这是因为它可能会从视图或表单中调用,并且可以访问cleaned_data
dict中的完整对象。管理器类的create()
方法是另一个django本身接受对象的例子。
模型图层方法的调用者应查找并将id转换为完整对象。
您可以覆盖save()
,但如果这样做,则应小心接受args
和**kwargs
如果模型跨越应用程序,则应考虑信号而不是覆盖save
不要试图巧妙地覆盖模型管理器create
方法。如果视图层创建新对象并保存它,则不会调用它。如果您需要在保存之前执行额外处理,则可以覆盖save
或__init__
或捕获信号。如果覆盖__init__
,您可以检查pk以确定它是否存在于数据库中。
我现在要将我的创建代码放在一个单独的方法中,直到找出我最喜欢哪种技术。
我认为这是向模型层添加方法的一套很好的指南。我错过了什么?