django:胖子模特和瘦小的控制者?

时间:2011-12-21 13:21:49

标签: python django model-view-controller

这是一般架构问题。我在许多地方读到,在MVC框架中,(1)模型应该很胖,控制器应该是瘦的。但是我也读过(2)细节取决于你正在开发的框架。那么,如果你在django中开发呢?

我对django的经验是,很多逻辑最终会被放入视图和表单中。不是“业务逻辑”,而是处理请求,会话等的细节。在代码行方面,这些细节往往超过操纵模型对象的业务逻辑。我做错了什么,或者这是django的工作原理?

3 个答案:

答案 0 :(得分:29)

MVC不是一种通用的解决方案,并且大部分时间都是错误的并且无法兑现其承诺:在实践中修改模型也需要在控制器中进行修改,因为它做错了。如果你真的想要Model和Controller之间的松散耦合,那么人们通常会忽略它 - 你必须使用service pattern (open as image)。几乎没有人真正这样做。

Django不是盲目地坚持PHP世界中的MVC大惊小怪/伪模式,而是pragmatic approach。因为在软件开发的共同现实中,开发人员为用户编程事物。然后,用户(您的老板,客户,客户......)将“看到”您的工作,并最终表达他最终想要“看到”它的意见。通过使用Django,开发人员可以采用更“面向视图”的开发模式并猜测:它使得最后期限更容易受到尊重,用户更满意。如果你考虑一下,它有“nosql-ish”的想法,即视图(一般视图,而不是django视图)应该是幕后发生的事情的老板。

我要感谢Django没有做错MVC,不像99%的PHP MVC实现那样。

另一方面,Django是唯一允许在应用程序之间进行适当隔离的框架。每个应用程序都可以:

  • 模型
  • 视图
  • 模板
  • 网址
  • 静态文件
  • 测试
  • 形式
  • 可选插件(管理员,ajax-choices的过滤器,django-authority的权限,django-notifications的通知等等)

因此,即使您的模型/视图/模板将被绑定,您的项目也可以相关地分为小型(也称为:易于维护)和松散耦合的应用程序。只有相关的模型/视图/模板/东西捆绑在一起。一个带有大胖视图和网址脚本的大胖模型脚本不是你想要的Django。例如,你不希望像Article和FootballMatch这样的两个模型类一起生活,你想要制作一个“文章”/“博客”应用程序和一个可以独立生活的“运动”应用程序。当然有时它们必须绑定,在这种情况下,在90%的情况下它在项目级别是可行的(如果你碰巧需要绑定模型或模板标签,你可以制作另一个应用程序,“blog_sport”)。

例如,在Model类中定义get_absolute_url()方法是一种非常常见的做法。是的,理论上必须包含业务逻辑的模型类现在与您的URL定义绑定。这在实践中有多糟糕?!!实际上这很棒,因为添加此方法需要两秒钟,然后您可以在使用模型的任何地方使用它:无论是在视图还是模板中。此外,其他应用程序(即django.contrib.admin)将使用它。

Django的另一个稍微复杂的例子是查询被懒惰地评估。这意味着,您的视图函数/类将定义一个类似blog_list = Blog.objects.all()的查询,但是如果它调用{%for blog in blog_list%},则查询实际上将在模板中执行。因此,在这种情况下,模板中会出现业务逻辑,如果在呈现模板之前出现问题:您保存了查询。但并非全部,如果您的模板只显示一个计数{{blog_list.count}},则选择查询将不会在所有中生成,只有一个计数查询将是执行。 “一般视图”决定了所需的业务逻辑。这远远不是MVC的承诺,但说实话:那有多实用?

我的观点是,你可以用错误的方式应用理论,做得对(这会减少你选择的所有语言包含的5 web 框架),或者只是在优雅和务实的方式让你的工作在很短的时间内完成:这是Django的选择。

答案 1 :(得分:3)

这取决于你的应用程序是什么,但Django的优点在于它不会强制你将逻辑代码放在你的视图或模型中,这是你的呼唤。

如果您认为某些逻辑与您的模型密切相关,那么您可以制定一个方法。规则(对我而言)是您的模型应该与环境无关(web-app,运行manage命令的Crontab等)。

我的政策是尽量将最低限度放在我的模特中。

顺便说一句,您不打算在模型中处理requestsessions,不是吗? 是一个坏主意。

答案 2 :(得分:0)

Django最大的问题是它们似乎通过添加 Forms 层来打破MVC模式。大多数文档都会引导您在表单中放置验证逻辑,而模型验证器仅通过表单保存调用这一事实只会强化此约定。但是在我看来这是一个糟糕的惯例,因为毕竟经常被验证的是将被转换为模型的数据。

如果您考虑将传统的Django项目转换为使用Django Rest Framework的API中心项目以及仅使用此API的单独前端客户端,那么最好的例子就是这样做。你不得不完全保留你的模型并保留大量的业务逻辑,而是必须通过你的表单并将所有逻辑移动到序列化器(不幸的是,Django Rest Framework也遵循Django破坏的MVC模式并增加了额外的“序列化器”层)。

我认为胖模型的方法是可行的。有关如何在Django here中实现它的更多信息。