在Django中放置跨越多个模型的业务逻辑的位置

时间:2012-07-07 20:46:30

标签: django model-view-controller django-models

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

在Django中放置跨越多个模型的业务逻辑?

一些可能性:

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

上下文

我有这个型号:

  1. 部门:参考公司的不同部门(风险,财务,IT,......)
  2. 员工:可能只属于一个部门一段时间,然后转到其他部门。
  3. 项目:每个部门可以有多个项目,一个项目属于多个部门。
  4. 成员资格:Employee和Department之间的中间表ManyToMany关系包括其他字段,如join_date和leave_date,重要字段是fk:Department,fk:Employee
  5. 历史:会员和项目之间的中间表,让我知道哪个员工参与了愿望项目,他在某个部门工作,重要的领域是fk:Membership,fk:Project。
  6. CurrentProjects:将部门与他们当前正在处理的项目联系起来的表。
  7. 假设我在Django管理员中并且我去了部门风险,而风险目前已经分配了Project1和Project2。当我添加一名新员工“Jhon Smith”(例如,使用部门中的内联表单)并按下保存按钮时,我希望模型历史记录更新时会显示以下信息:

    Membership table (only important fields):
    
    pk   Department   Employee     join_date   leave_date
    20   Risk         Jhon Smith   xxxx        xxxx
    
    
    History Table (only important fields):
    
    Membership   Project
    20           Project1
    20           project2
    

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

    问题是将这个逻辑放在Django中的哪个位置?你可以看到这个逻辑涉及多个模型,一些可能性是:

    • 在某些观点中(我不这么认为,它必须在admin interfase和其他地方工作)
    • 在会员,部门或员工模型/表格的清洁方法中?
    • 在会员,部门或员工模型/表单的保存方法中?
    • 我必须拆分逻辑并使用信号之类的东西? (某些例子?)
    • 其他?
    • 我复杂化了一切? =)

    注意事项:如果代码可以在流程中的任何一点生成一个valueerror并且用户/管理员能够以无界形式看到此错误,那将是很好的。

2 个答案:

答案 0 :(得分:3)

我只是评论逻辑应该存在的方面。这对我来说听起来像模型逻辑。 Django有一个略微复杂的MVC概念。当它纯粹的数据关系时,我相信它的所有模型逻辑。我建议尽可能将方法放在尽可能接近模型的位置,并简单地从触发模型中调用最小的调用。

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

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

模型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模块。他们更像是行动或帮助者。

答案 1 :(得分:0)

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

我希望你理解我的观点。如果没有,请告诉我,以便我能更好地解释它(可能有一个例子)。

但是,当我理解你的问题和你的模型时,我认为你不需要那个历史表。它将重复信息......

因此,如果您的Project模型具有此信息(日期范围),则解决方案应该存在于经理中,因为只需找到您希望存在于多个表中的信息... < / p>

希望它有所帮助!