将models.py拆分成几个文件

Posted

技术标签:

【中文标题】将models.py拆分成几个文件【英文标题】:Split models.py into several files 【发布时间】:2011-09-14 06:23:14 【问题描述】:

我正在尝试将我的应用程序的 models.py 拆分为多个文件:

我的第一个猜测是这样做:

myproject/
    settings.py
    manage.py
    urls.py
    __init__.py
    app1/
        views.py
        __init__.py
        models/
            __init__.py
            model1.py
            model2.py
    app2/
        views.py
        __init__.py
        models/
            __init__.py
            model3.py
            model4.py

这不起作用,然后我找到了this,但是在这个解决方案中我仍然有问题,当我运行python manage.py sqlall app1 时,我得到了类似的东西:

BEGIN;
CREATE TABLE "product_product" (
    "id" serial NOT NULL PRIMARY KEY,
    "store_id" integer NOT NULL
)
;
-- The following references should be added but depend on non-existent tables:
-- ALTER TABLE "product_product" ADD CONSTRAINT "store_id_refs_id_3e117eef" FOREIGN KEY     ("store_id") REFERENCES "store_store" ("id") DEFERRABLE INITIALLY DEFERRED;
CREATE INDEX "product_product_store_id" ON "product_product" ("store_id");
COMMIT;

对此我不太确定,但我担心The following references should be added but depend on non-existent tables:的部分

这是我的 model1.py 文件:

from django.db import models

class Store(models.Model):
    class Meta:
        app_label = "store"

这是我的 model3.py 文件:

from django.db import models

from store.models import Store

class Product(models.Model):
    store = models.ForeignKey(Store)
    class Meta:
        app_label = "product"

显然有效,但我在alter table 中得到了评论,如果我尝试这个,同样的事情会发生:

class Product(models.Model):
    store = models.ForeignKey('store.Store')
    class Meta:
        app_label = "product"

那么,我应该手动运行 alter for references 吗?这可能会给我带来南方的问题吗?

【问题讨论】:

如果您尝试from app1.models.model1 import Store,模型 3 会发生什么? 另外你可能想看看***.com/questions/5534206/… 【参考方案1】:

对于任何使用 Django 1.9 的人,现在框架都支持它,而无需定义类元数据。

https://docs.djangoproject.com/en/1.9/topics/db/models/#organizing-models-in-a-package

注意:对于 Django 2,it's still the same

manage.py startapp 命令创建一个包含 models.py 文件的应用程序结构。如果您有许多模型,将它们组织在单独的文件中可能会很有用。

为此,请创建一个模型包。删除 models.py 并创建一个 myapp/models/ 目录,其中包含 __init__.py 文件和用于存储模型的文件。您必须导入 __init__.py 文件中的模型。

所以,在你的情况下,对于像这样的结构

app1/
    views.py
    __init__.py
    models/
        __init__.py
        model1.py
        model2.py
app2/
    views.py
    __init__.py
    models/
        __init__.py
        model3.py
        model4.py

你只需要这样做

#myproject/app1/models/__init__.py:
from .model1 import Model1
from .model2 import Model2

#myproject/app2/models/__init__.py:
from .model3 import Model3
from .model4 import Model4

关于导入所有类的注意事项:

显式导入每个模型而不是使用from .models import * 的优点是不会弄乱命名空间,使代码更具可读性,并使代码分析工具保持有用。

【讨论】:

如果有人想知道它是否仍然是最新的 Django 2.0 docs.djangoproject.com/en/2.0/topics/db/models/… 注意:当您开始使用models.py 并想稍后迁移时,这通常无法正常工作。在这种情况下,您必须删除迁移和数据库:/ 或手动解决所有迁移文件中的所有错误 仍然是最佳答案。可以确认这在 2.1+ 中仍然有效 我没有看到 @tuergeist 在 Django 3.0 中指出的问题。似乎像魅力一样工作 我在 python 3.2 中运行迁移时遇到问题。这个答案似乎仍然是最新的,因为关于此的文档仍然相同:docs.djangoproject.com/en/3.2/topics/db/models【参考方案2】:

我会做以下事情:

myproject/
    ...
    app1/
        views.py
        __init__.py
        models.py
        submodels/
            __init__.py
            model1.py
            model2.py
    app2/
        views.py
        __init__.py
        models.py
        submodels/
            __init__.py
            model3.py
            model4.py

然后

#myproject/app1/models.py:
    from submodels/model1.py import *
    from submodels/model2.py import *

#myproject/app2/models.py:
    from submodels/model3.py import *
    from submodels/model4.py import *

但是,如果你没有充分的理由,把model1和model2直接放在app1/models.py中,model3和model4放在app2/models.py中

---第二部分---

这是 app1/submodels/model1.py 文件:

from django.db import models
class Store(models.Model):
    class Meta:
        app_label = "store"

因此更正您的 model3.py 文件:

from django.db import models
from app1.models import Store

class Product(models.Model):
    store = models.ForeignKey(Store)
    class Meta:
        app_label = "product"

已编辑,以防有人再次出现这种情况: 查看 django-schedule 以获取执行此操作的项目示例。 https://github.com/thauber/django-schedule/tree/master/schedule/models https://github.com/thauber/django-schedule/

【讨论】:

关于这个答案我遇到了另一个问题,当在 models2.py 中制作类似 from product.models import Product: ImportError: No module named models 你会这样做来为每个文件维护一个类。 “为什么”是希望减小大量 models.py 文件的大小。当我的代码增长到超过 15k 行时,我最近这样做了。不过写的很棒。这个过程相当简单。主要的警告是你必须记住定义一个显式的 app_label,因为 Django 默认从直接模块中提取它。 在 2016 年尝试一下。这篇文章的第二部分还需要吗?我只将类移动到单独的文件中,写了我的__init__.py,一切似乎都正常。我不必更正我的模型文件。我能够从 shell 和 django 管理员获取和创建对象。我已经尝试 django 一周了,所以我想知道最新版本现在是否允许这种情况发生? @Vic:对于较新版本的 Django,Meta 类中的 app_label 不再是必需的。见code.djangoproject.com/wiki/CookBookSplitModelsToFiles【参考方案3】:

我实际上遇到了一个关于你所问问题的教程,你可以在这里查看它:

http://paltman.com/breaking-apart-models-in-django/

一个可能相关的关键点 - 您可能希望使用 Meta 类上的 db_table 字段将重定位的类指向它们自己的表。

我可以确认这种方法在 Django 1.3 中有效

【讨论】:

【参考方案4】:

Django 3的相关链接是:

https://docs.djangoproject.com/en/3.2/topics/db/models/#organizing-models-in-a-package

指向先前版本文档的链接已损坏。里面的例子很简洁:

为此,请创建一个模型包。删除 models.py 并创建一个 myapp/models/ 目录,其中包含 init.py 文件和用于存储模型的文件。您必须在 init.py 文件中导入模型。

例如,如果模型目录中有organic.py 和synthetic.py:

from .organic import Person
from .synthetic import Robot

【讨论】:

【参考方案5】:

最简单的步骤:

    在您的应用中创建模型文件夹(文件夹名称应为 model) 从应用目录中删除model.py文件(删除时备份文件) 然后在模型文件夹中创建 init.py 文件 并在init.py文件中写简单的一行 在模型文件夹中创建模型文件后,模型文件名应与类名相同,如果类名是“Employee”,则模型文件名应类似于“employee.py” 在模型文件中定义您的数据库表之后,就像在 model.py 文件中写入一样 保存

我的代码:从 django_adminlte.models.employee 导入员工

对于您的:从 app_name.models.model_file_name_only 导入 Class_Name_which_define_in_model_file


__init__.py

from django_adminlte.models.employee import Employee

model/employee.py (employee is separate model file)

from django.db import models

class Employee(models.Model):
eid = models.CharField(max_length=20)
ename = models.CharField(max_length=20)
eemail = models.EmailField()
econtact = models.CharField(max_length=15)

class Meta:
    db_table = "employee"
    # app_label = 'django_adminlte'
    
def __str__(self):
    return self.ename

【讨论】:

这正是他想要解决的问题。此解决方案将在 django 2.x 中导致 RuntimeError ModelX doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS.【参考方案6】:

我写了一个可能有用的脚本。

github.com/victorqribeiro/splitDjangoModels

它通过正确的命名和导入将模型拆分为单独的文件;它还会创建一个 init 文件,以便您可以一次导入所有模型。

如果这有帮助,请告诉我

【讨论】:

以上是关于将models.py拆分成几个文件的主要内容,如果未能解决你的问题,请参考以下文章

如何把一个压缩好的文件,拆分成几个压缩文件?

如何将实时stdout流拆分成几个文件?

Django models拆分

不在models.py中的models

为啥 django 强制所有模型类都在 models.py 中?

模型分离(选做)