【问题标题】:models.py getting huge, what is the best way to break it up?models.py 越来越大,最好的方法是什么?
【发布时间】:2010-11-12 17:36:01
【问题描述】:

我的主管的指示: “我想避免在models.py 中添加任何逻辑。从现在开始,让我们将其用作访问数据库的唯一类,并将所有逻辑保留在使用模型类或包装它们的外部类中。”

我觉得这是错误的方法。我觉得为了保持文件小而将逻辑排除在模型之外是一个坏主意。如果模型中的逻辑是最好的,那么无论文件大小如何,它都应该去那里。

那么有没有一种简单的方法来使用包含?在 PHP 中,我想向主管建议我们只有 models.py include() 来自其他地方的模型类。从概念上讲,这将允许模型具有我们想要的所有逻辑,同时通过增加文件数量来减小文件大小(这会减少冲突等修订控制问题)。

那么,有没有一种简单的方法可以从 models.py 文件中删除模型类,但模型仍然可以与所有 Django 工具一起使用?或者,对于“大型”models.py 文件的一般问题,是否有完全不同但优雅的解决方案?任何意见将不胜感激。

【问题讨论】:

  • 你知道import语句,对吧?
  • 附言。我不是说冒犯,我只是想知道你在哪里。
  • 是的,但我不知道 django 的管理工具是否可以仅使用导入语句来拉入模型。我宁愿在这里问,也不愿花大量时间尝试使用普通的 ole 导入来发现 django 的工具不能很好地与它们配合使用。我承认我对 python 和 django 比较陌生,所以我可能只是对 import 语句有一个简单的理解......

标签: python django django-models models


【解决方案1】:

模型类包含对模型进行操作的方法是很自然的。如果我有一个 Book 模型,带有一个方法 book.get_noun_count(),那就是它所属的地方——我不想写“get_noun_count(book)”,除非该方法实际上本质上属于其他一些包。 (它可能——例如,如果我有一个使用“get_amazon_product_id(book)”访问亚马逊 API 的包。)

当 Django 的文档建议将模型放在单个文件中时,我感到畏缩,我从一开始就花了几分钟时间弄清楚如何将其拆分为适当的子包。

site/models/__init__.py
site/models/book.py

__init__.py 看起来像:

from .book import Book

所以我仍然可以写“from site.models import Book”。


以下内容仅适用于 Django 1.7 之前的版本,请参阅 https://code.djangoproject.com/ticket/3591

唯一的技巧是您需要显式设置每个模型的应用程序,这是由于 Django 中的一个错误:它假定应用程序名称是模型路径中的倒数第三个条目。 “site.models.Book”的结果是“site”,这是正确的; “site.models.book.Book”使它认为应用程序名称是“models”。这对 Django 来说是一个非常讨厌的 hack。它可能应该在已安装应用程序列表中搜索前缀匹配。

class Book(models.Model):
    class Meta: app_label = "site"

您可能可以使用基类或元类来概括这一点,但我还没有为此烦恼。

【讨论】:

  • +1 我已经成功使用了它。虽然 S. Lott 在多个应用中是个好主意,但这是现在的解决方案。
  • 当您的模型紧密且内在相关时,我认为将事物拆分为一堆应用程序没有多大好处。
  • 这让我很感兴趣。我阅读了发布的 django wiki 链接 scompt 并发现:“在当前主分支中,已验证在没有 Meta 类 app_labels 的情况下可以正常工作。”那么这是否意味着如果您正在使用主分支,我们可以丢弃 Meta: app_label 的东西?这很令人困惑,因为它是在关于解决这个问题的票的评论之后。
  • 我刚刚用trunk测试过(今天早些时候,r11286);如果未设置 app_name,则模型根本不会出现在“sqlall appname”中,并且可能不会由 syncdb 创建(但我不使用它,因此无法对其进行测试)。这是一个相当混乱的错误案例,因为它不会触发任何错误;它只是默默地没有出现。
  • 哇,近 10 年后,我仍然喜欢这个解决方案。同意这是一种比将代码拆分为更小的应用程序更好的方法,在我看来,这可能会导致代码库难以推理。
【解决方案2】:

Django 旨在让您构建许多小应用程序而不是一个大应用程序。

每个大型应用程序内部都有许多小应用程序在努力争取免费。

如果您的models.py 感觉很大,那么您做的太多了。停止。放松。分解。

寻找更小、可能可重复使用的小型应用程序组件或片段。您不必实际上重复使用它们。只需将它们视为潜在的可重复使用。

考虑您的升级路径并分解您将来可能想要替换的应用程序。您不必实际上替换它们,但您可以将它们视为一个独立的编程“模块”,将来可能会被更酷的东西取代。

我们有大约十几个应用程序,每个model.py 不超过大约 400 行代码。他们都非常关注不到大约六个离散类定义。 (这些不是硬性限制,它们是对我们代码的观察。)

我们很早就并且经常分解。

【讨论】:

  • 正确。任何重要的网络应用程序都将是几个小的“应用程序”。提示一下 contrib 和其他流行的应用程序,用户身份验证是一个应用程序,标记是另一个应用程序,用户配置文件是另一个,等等。
  • 虽然这是“正确”的方式,并且有助于了解,但这并不是我想要的。如果无法知道我在寻找什么样的答案,我深表歉意。 :)
  • @Eddified:如果你不这样做,它只会变得更糟。现在开始拆分。
  • 很有趣,此时此刻,我正在听 Jacob Kaplan Moss(在 OSCON)详细解释这一点;-)。
  • Glenn Maynard 对此的回答要好得多。将一个复杂的 web 应用程序划分为多个应用程序当然是一个好习惯,但在应用程序中重构一个 model.py 文件也是如此。这两个动作可以是正交的。
【解决方案3】:

我不太清楚您可能遇到的许多问题中的哪一个。以下是一些可能的答案:

  • 同一文件中的多个模型

    将它们放入单独的文件中。如果有依赖,使用 import 拉入 其他型号。

  • models.py 中的无关逻辑/实用函数

    将额外的逻辑放入单独的文件中。

  • 从数据库中选择一些模型实例的静态方法

    在单独的文件中创建一个新的Manager

  • 与模型明显相关的方法

    save、__unicode__ 和 get_absolute_url 是示例。

【讨论】:

    猜你喜欢
    • 2010-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-02
    • 2015-12-19
    • 2017-10-15
    • 2019-07-01
    相关资源
    最近更新 更多