将models.py拆分为几个文件


89

我正在尝试将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

这不起作用,然后我发现了这个问题,但是在此解决方案中,我仍然遇到问题,当我运行时,出现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 reference吗?这可能给我带来南方问题吗?


如果尝试,模型3会发生什么from app1.models.model1 import Store
James Khoury

Answers:


32

我将执行以下操作:

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/


1
关于这个答案,当我在models2.py中进行如下操作时,我遇到了另一个问题from product.models import Product:ImportError:No module named models
diegueus9 2011年

68
您可以通过这种方式来维护每个文件一个类。
worc

50
“为什么”将是希望减少海量models.py文件的大小。当我的代码增长到超过15,000行时,我最近才这样做。很棒的文章。这个过程非常简单。需要注意的主要问题是,必须定义一个显式的app_label,因为Django默认是从即时模块中提取出来的。
塞林2014年

1
在2016年尝试一下。仍然需要这篇文章的第二部分吗?我只将类移到了单独的文件,写了我的文件,__init__.py一切似乎都正常。我不必更正我的模型文件。我能够从Shell和django管理员获取并创建对象。我一直在尝试django大约一个星期,所以我想知道最新版本是否允许这种情况发生?
2016年

3
@Vic:较新版本的Django不再需要Meta类中的app_label。参见code.djangoproject.com/wiki/CookBookSplitModelsToFiles
jrial

147

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

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

注意:对于Django 2,它仍然相同

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 *的优点是不会使名称空间混乱,使代码更具可读性并保持代码分析工具有用。


5
如果有人想知道它是否仍与Django 2.0保持
docs.djangoproject.com/en/2.0/topics/db/models/…– NaturalBornCamper

6
注意:通常,当您开始使用models.py并且以后要迁移时,它通常无法正常工作。在这种情况下,您必须删除您的迁移和数据库:/或手动解决所有迁移文件中的所有错误
tuergeist

最好的答案还是。可以确认此版本在2.1+版本中仍然有效
Roys

我看不到Django 3.0中@tuergeist指出的问题。似乎像魅力一样工作
caram


1

最简单的步骤:

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

我的代码:从django_adminlte.models.employee导入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

2
这正是他要解决的问题。此解决方案将RuntimeError ModelX doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS.在Django 2.x中引起。
radtek

0

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

github.com/victorqribeiro/splitDjangoModels

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

让我知道这是否有帮助

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.