【问题标题】:What kind of data do I pass into a Django Model.save() method?我将什么样的数据传递给 Django Model.save() 方法?
【发布时间】:2010-06-01 05:10:01
【问题描述】:

假设我们正在 Django 中发布这样的表单:

rate=10
items= [23,12,31,52,83,34]

项目是项目模型的主键。我有一堆业务逻辑,它们将根据这些数据、一些数据库查找的结果和一些业务逻辑运行并创建更多项目。我想将该逻辑放入保存信号或覆盖另一个模型的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() 方法是否更好接受:

  • 请求对象(我不太喜欢这种耦合)
  • 作为参数或 kwargs 的表单数据(主键列表和其他表单字段)
  • 项目列表(调用方表单或视图将查找项目列表并创建一个列表并传入其他表单字段)
  • 其他方法?

我知道这有点主观,但我想知道总体思路是什么。我查看了很多代码,但很难找到我喜欢的模式。

澄清:

好的,所以共识是它应该进入模型上的不同功能,例如inventory.calculate(...),然后它将创建所有内容,执行业务逻辑等......这很高兴知道。我的问题仍然存在:将表单数据查找到 db 对象的最佳位置在哪里?这个函数的调用者应该将主键转换为数据库模型,还是模型方法应该接受主键并自己做?这是我想在整个项目范围内以同样的方式做的事情。

说明 2:

好的,所以现在对于覆盖 save 是否可以存在一些分歧。

当您获得简单 CRUD 类型操作的表单提交时,您将模型和值作为参数传递给 Model.objects.create(...) 或覆盖 save 或使用信号或其他方式。

我认为我的问题的核心是:

如果表单提交有用于业务逻辑的相关模型,那么您需要将一些业务逻辑写入模型层。当你这样做时,它应该去哪里,该方法应该接受对象列表还是 id 列表?模型 API 应该接受对象还是 id?

【问题讨论】:

  • 我不完全明白你为什么不想使用信号,如果是这样我猜会有你的 Item 对象的实例通过,这应该回答你的问题?
  • 我愿意为此使用信号。过去,我只是将所需的所有内容传递给 Inventory.objects.create() 方法。这适用于简单的情况。在这里,当我创建一个新的 Inventory 模型对象时,我将它与一堆现有模型相关联并且我创建了一组基于某些业务逻辑的相关模型。我希望 like 将该逻辑推入模型层。在您看来 - 业务逻辑代码应该采用什么方法,谁应该负责查找外键?业务逻辑的调用者还是方法本身?感谢您的意见。

标签: python django django-models


【解决方案1】:

好的,所以我得到的前两个答案现在已经被其他人反驳了。我一直在研究这个问题,我将自己尝试回答。如果您认为这是正确的,请投票和/或如果您不同意我的推理,请发表评论。

  • 模型上的方法应该接受对象和对象列表,而不是 id 作为 int/long 或 id 列表或类似的东西。这是因为它可能会从视图或表单中调用,并且他们可以访问来自cleaned_data dict 的完整对象。管理器类上的 create() 方法是 django 本身接受对象的另一个示例。

  • 模型层方法的调用者应该查找并将 id 转换为完整的对象。

  • 你可以覆盖save(),但如果你这样做,你应该小心接受args和**kwargs

  • 如果模型跨越应用程序,您应该考虑信号而不是覆盖save

  • 不要试图巧妙地覆盖模型管理器create 方法。如果视图层创建一个新对象并保存它,它不会被调用。如果需要在保存前进行额外处理,可以覆盖save 或__init__ 或捕获信号。如果你覆盖__init__,你可以检查一个pk以确定它是否存在于数据库中。

我现在将把我的创建代码放在一个单独的方法中,直到我弄清楚我最喜欢哪种技术。

我认为这是向模型层添加方法的一套很好的指南。我错过了什么?

【讨论】:

    猜你喜欢
    • 2021-09-07
    • 2018-08-04
    • 1970-01-01
    • 2021-11-24
    • 2012-01-04
    • 1970-01-01
    • 1970-01-01
    • 2018-03-26
    • 2020-12-02
    相关资源
    最近更新 更多