将models.py拆分为多个文件

die*_*us9 77 python django import django-models

我正在尝试将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
Run Code Online (Sandbox Code Playgroud)

这不起作用,然后我找到了这个,但在这个解决方案中我仍然有一个问题,当我运行时,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;
Run Code Online (Sandbox Code Playgroud)

我对此并不十分肯定,但我很担心这一部分 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"
Run Code Online (Sandbox Code Playgroud)

这是我的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"
Run Code Online (Sandbox Code Playgroud)

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

class Product(models.Model):
    store = models.ForeignKey('store.Store')
    class Meta:
        app_label = "product"
Run Code Online (Sandbox Code Playgroud)

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

Vic*_*Vic 118

对于Django 1.9上的任何人来说,它现在都得到了框架的支持,而没有定义类元数据.

https://docs.djangoproject.com/en/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
Run Code Online (Sandbox Code Playgroud)

你只需要做

#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
Run Code Online (Sandbox Code Playgroud)

反对导入所有类的注释:

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

  • 注意:当您开始使用`models.py`并希望稍后迁移时,这通常无法正常工作.在这种情况下,您必须删除迁移和数据库:/或手动解决所有迁移文件中的所有错误 (5认同)
  • 我没有看到 @tuergeist 在 Django 3.0 中指出的问题。似乎有魅力 (4认同)
  • 如果有人想知道它是否仍与Django 2.0保持最新,https://docs.djangoproject.com/en/2.0/topics/db/models/#organizing-models-in-a-package (2认同)

Ted*_*Ted 25

我甚至无法想象你为什么要这样做.但我会假设你有充分的理由.如果我出于某种原因需要这样做,我会做以下事情:

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
Run Code Online (Sandbox Code Playgroud)

然后

#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 *
Run Code Online (Sandbox Code Playgroud)

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

- -第二部分 - -

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

from django.db import models
class Store(models.Model):
    class Meta:
        app_label = "store"
Run Code Online (Sandbox Code Playgroud)

从而更正你的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"
Run Code Online (Sandbox Code Playgroud)

编辑,以防再次出现在某人身上:查看django-schedule,了解一个完成此项目的项目示例. https://github.com/thauber/django-schedule/tree/master/schedule/models https://github.com/thauber/django-schedule/

  • 你会这样做,以保持每个文件一个类. (66认同)
  • "为什么"是减少大量`models.py`文件大小的愿望.我最近做了这个,当我的代码超过15k行时.很棒的写作.这个过程非常简单.主要的警告是你必须记住定义一个明确的app_label,因为Django默认从立即模块中提取它. (49认同)
  • @Vic:对于较新版本的Django,不再需要Meta类中的app_label.请参阅https://code.djangoproject.com/wiki/CookBookSplitModelsToFiles (2认同)

Ada*_*ers 11

我实际上遇到了你正在询问的教程,你可以在这里查看:

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

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

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


Kev*_*n K 10

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
Run Code Online (Sandbox Code Playgroud)