2012-07-07 105 views
0

您不需要阅读所有这篇文章以帮助我回答问题,本文的其余部分仅仅是问题出现的上下文,但一般问题是:何处放置商业逻辑,跨越Django中的多个模型

在哪里把商业逻辑,跨越多个模型在Django?

一些posibilites:

  • 一些视图? (我不这么认为,它必须在管理和若干意见的工作,DRY)
  • 模型/表格保存方法是什么?(如何?)
  • 清洁methos模型/表格?(如何?)
  • 拆分逻辑和使用信号?(如何?)
  • 其他?

语境:

我有这个型号:

  1. 部:在公司引用不同的部门(风险,金融,IT,...)
  2. 员工:五月一段时间只属于一个部门,然后更换为其他部门。
  3. 项目:每个部门可以有多个项目,一个项目属于多个部门。
  4. 成员:员工和部门多对多的关系,其中包括其他领域,如join_date和leave_date之间的中间表,重要的领域是FK:部门,FK:员工
  5. 历史:成员和项目之间的中间表,让我知道哪个员工参与了他在某个部门工作的愿望项目,重要的领域是fk:会员,fk:项目。
  6. CurrentProjects:当前将部门与其正在处理的项目相关联的表。

supose我在Django管理员,我去部门风险,风险目前Proyect1和Project2签署。当我添加一个新员工“JHON史密斯”(例如,使用系内联形式),然后按保存按钮,我想要的模型历史被用该信息更新:

 
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中放置这个逻辑的地方?你可以看到这个逻辑涉及倍数的机型,有些posibilities是:

  • 在一些视图(我不这么认为,它必须在管理interfase和在其他地方工作)
  • 在的清洁方法会员,部门或员工模型/表单?
  • 在会员,部门或员工模型/表单的保存方法中?
  • 我必须拆分逻辑并使用类似信号的东西吗? (一些例子?)
  • 其他?
  • 我过了复杂的永恒? =)

注意事项:如果代码可能在进程中的任意位置生成valueerror并且用户/管理员能够以无界形式查看此错误,那将会很好。

谢谢

+0

您是否探索过信号? – jdi 2012-07-07 21:37:17

+0

@jdi我现在正在审查这个主题,但是你对如何在这种情况下使用它们有一些见解吗? – javier 2012-07-07 21:52:53

+0

看到我的答案。我谈论这个。 – jdi 2012-07-07 22:07:31

回答

3

我只是评论逻辑应该在哪里生活的方面。这一切听起来都像我的模型逻辑。 Django的MVC概念稍有混淆。当它纯粹的数据关系我相信它的所有模型逻辑。我建议将这些方法尽可能接近它们所影响的模型,并简单地从触发模型中调用最小的调用。

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

有一些内置信号,例如之前和after a save在模型上,这意味着如果你正在寻找一个保存触发器,你将不必发出一些自定义。但让我们说在一个模型逻辑的不同点上,你需要发出一个自定义信号,比如“Name changed”,你可以发出你自己的信号。

模型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模块的习惯“控制器模型“逻辑。他们更像是行动或助手。

+0

感谢您的回答,我现在试图使用这种方法,但我仍然怀疑是否有更好的方法,所以我会继续研究和发布,而且,我对你的utils.py文件很感兴趣,你有什么样的代码? =) – javier 2012-07-07 22:20:01

+0

@javier:utils只是可能像'do_something_with_something'这样的函数。基本上,我只是试图将重逻辑的数量保持在模型之外,并将其限制为简单的拉取和表示数据的方式。我真的不会在正确或错误的地方加入代码。当您设计一个应用程序时,信号通常会很有用,该应用程序应该被分配并用于任何其他项目。您允许项目所有者连接到您的应用程序的信号。但是如果你正在设计你自己的项目,那么从一个应用程序导入另一个应用程序并使用逻辑就没有什么坏处。 – jdi 2012-07-07 22:39:53

+0

+1用于放置utils.py – Soask 2012-07-19 15:53:27

0

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

我希望你能理解我的观点。如果不是,请告诉我,这样我可以更好地解释它(也许有一个例子)。

但正如我理解你,你的模型,我认为你不需要历史表。它会复制信息...

因此,如果您的Project模型具有此信息(日期范围),解决方案应该存在于管理器中,因为它只是查找您希望生活在多个表中的信息...

希望它能帮助!

+0

感谢您的回答,我理解您的观点,但事实是,逻辑比这更复杂一点,日期不仅仅是可靠的实际项目表,但即使日期是可靠的,我想知道哪里是最好的地方把这种商业逻辑,跨越多个模型。 – javier 2012-07-07 22:01:43

+0

我认为答案在模型中。我不会更改模型的保存方法,因为我认为它应该是一个愚蠢的方法,只是为了管理该模型/对象的数据库问题。所以,我认为它应该是一种表单保存方法,因为它涉及多个模型来保存。如果你想控制一切都是一致的,你可以将这个逻辑添加到表单清理方法中。 – marianobianchi 2012-07-07 22:11:00

+0

@marianobibanchi我试图理解你的评论,你是否在提出跨越多个模型的商业逻辑必须从这些模型的形式来管理?如果我必须为同一模型加上其他api和django管理员的多种表单,您对DRY原则有什么看法? – javier 2012-07-07 22:25:41