1

你不需要阅读所有这篇文章来帮助我回答这个问题,这篇文章的其余部分只是问题出现的上下文,但一般问题是:

在 Django 中将跨多个模型的业务逻辑放在哪里?

一些可能性:

  • 一些观点?(我不这么认为,它必须在管理员和几个视图中工作,DRY)
  • 在模型/表单中保存方法?(如何?)
  • 模型/表单中的清洁方法?(如何?)
  • 拆分逻辑并使用信号?(如何?)
  • 其他?

语境:

我有这个模型:

  1. 部门:参考公司的不同部门(风险、财务、IT、...)
  2. 员工:可能在一段时间内只属于一个部门,然后转入另一个部门。
  3. 项目:每个部门可以有多个项目,一个项目属于多个部门。
  4. Membership:Employee 和 Department ManyToMany 关系之间的中间表,包括 join_date 和 leave_date 等其他字段,重要字段是 fk:Department,fk:Employee
  5. 历史:Membership 和 Project 之间的中间表,让我知道哪个员工参与了希望项目,当他在某个部门工作时,重要的字段是 fk:Membership,fk:Project。
  6. CurrentProjects:将部门与他们当前正在进行的项目相关联的表格。

假设我在 Django 管理员中,我去部门 Risk,并且 Risk 目前已分配 Project1 和 Project2。当我添加一个新员工“Jhon Smith”(例如,在部门中使用内联表单)并按下保存按钮时,我希望模型历史记录使用以下信息进行更新:

成员表(仅重要字段):

pk 部门员工 join_date leave_date
20 风险 Jhon Smith xxxx xxxx


历史表(仅重要字段):

会员项目
20 项目1
20个项目2

我的意思是当一个新员工被分配到一个新部门时,该部门的所有实际项目都必须分配给历史表中的该成员资格员工部门。

问题是在 Django 中将这个逻辑放在哪里?如您所见,此逻辑涉及多个模型,一些可能性是:

  • 在某些方面(我不这么认为,它必须在管理界面和其他地方工作)
  • 在 Membership、Department 或 Employee 模型/表单的 clean 方法中?
  • 在 Membership、Department 或 Employee 模型/表单的保存方法中?
  • 我必须拆分逻辑并使用信号之类的东西?(一些例子?)
  • 其他的?
  • 我把一切都复杂化了?=)

注意事项:如果代码可以在过程中的任何时候生成 valueerror 并且用户/管理员能够以无限制的形式看到这个错误,那就太好了。

4

2 回答 2

3

我只是在评论逻辑应该存在的方面。这对我来说听起来像是模型逻辑。Django 对 MVC 的概念有些混杂。当它纯粹是数据关系时,我相信它的所有模型逻辑。我建议将方法尽可能靠近它们影响的模型,并简单地从触发模型中进行最小的调用。

如果您非常关心应用程序的解耦,那么您可以使用信号。模型 A 不知道它需要在保存期间调用 XYZ,而是采用了另一种方式。模型 A 只是发出一个信号。XYZ 将负责连接到信号。你甚至可以在一个完全通用的项目应用程序中定义你的信号,在这种情况下,触发或接收模型都不知道彼此的动作。它只是将它们绑定在一起。

有一些内置信号,例如在模型上保存之前和之后,这意味着如果您正在寻找保存触发器,则不必发出自定义内容。但是让我们说在一个模型逻辑的各个点上,您需要发出一个自定义信号,例如“名称已更改”,您可以发出自己的信号。

A型

import django.dispatch

name_changed = django.dispatch.Signal(providing_args=["name"])

class ModelA:
    ...

    def foo:
        # something happened here
        name_changed.send(sender=self, name=the_name)

B、C、D 型

from myApp.modelA import name_changed

name_changed.connect(modelB.handle_name_change, dispatch_uid="my_unique_identifier")
name_changed.connect(modelC.handle_name_change, dispatch_uid="my_unique_identifier")
name_changed.connect(modelD.handle_name_change, dispatch_uid="my_unique_identifier")

就我个人而言,我习惯为需要一些通用“控制器模型”逻辑的应用程序创建一个 utils.py 模块。它们更像是动作或助手。

于 2012-07-07T21:47:48.900 回答
0

也许问题在于您那里的“历史”表。我不知道你的Project表中有什么样的信息。但是,如果每个项目都有开始和结束日期,那么您的历史表正在处理重复信息。在这种情况下,如果您想知道员工在哪个项目中工作,您只需要知道该员工在该部门工作的日期,然后您需要找到该部门在该部门之间开发的项目。上一个日期范围。

我希望你明白我的意思。如果不是,请告诉我,以便我更好地解释(也许有一个例子)。

但是,当我了解您的问题和模型时,我认为您不需要该历史记录表。它会重复信息...

因此,如果您的Project模型具有此信息(日期范围),则解决方案应该存在于管理器中,因为只需找到您想要存在于多个表中的信息......

希望能帮助到你!

于 2012-07-07T21:48:44.117 回答