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"

したがって、参照の変更を手動で実行する必要がありますか?これは私に南の問題をもたらすかもしれませんか?


試してみると、モデル3ではどうなりますfrom app1.models.model1 import Storeか?
James Khoury 2011年

回答:


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に配置します。

---第2部---

これは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:modelsという名前のモジュールがありません
diegueus9 2011年

68
この方法で、ファイルごとに1つのクラスを維持します。
worc 2013年

50
「理由」は、大規模なmodels.pyファイルのサイズを縮小したいという願望です。私は最近、15,000行を超えるコードに成長したときにこれを行いました。しかし素晴らしい記事。プロセスはかなり簡単です。Djangoはデフォルトでイミディエートモジュールからこれを抽出するため、主な注意点は、明示的なapp_labelを定義することを忘れないでください。
セリン2014年

1
2016年にこれを試してみてください。この投稿の2番目の部分はまだ必要ですか?クラスを別々のファイルに移動し、自分で書いただけで__init__.py、すべてが正常に機能しているようです。モデルファイルを修正する必要はありませんでした。シェルとdjango管理者からオブジェクトをフェッチして作成することができます。私は1週間ほどdjangoを試してきたので、最新バージョンでこれが可能になるかどうか疑問に思っていますか?
Vic 2016年

3
@Vic:Metaクラスのapp_labelは、新しいバージョンのDjangoでは不要になりました。code.djangoproject.com/wiki/CookBookSplitModelsToFiles
jrial

147

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

あなたはする必要があるだけです

#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
それはジャンゴで最新の状態にまだ2.0だ場合ケースで誰かが疑問に思っているdocs.djangoproject.com/en/2.0/topics/db/models/...
NaturalBornCamper

6
注:これは通常、開始してmodels.py後で移行したい場合は正しく機能しません。その場合、移行とデータベースを削除する必要があります:/または、すべての移行ファイルのすべてのエラーを手動で解決する
tuergeist 2018年

それでもベストアンサー。2.1+でこのまだ作業を確認することができます
ロイズ・

Django3.0で@tuergeistが指摘した問題は見当たりません。魅力のように機能しているようです
caram

11

私は実際にあなたが何を求めているのかについてのチュートリアルに出くわしました、あなたはそれをここで見ることができます:

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

おそらく関連する重要なポイントの1つは、Metaクラスのdb_tableフィールドを使用して、再配置されたクラスを独自のテーブルに戻すことです。

このアプローチがDjango1.3で機能していることを確認できます


そのリンクは404を与えます
ブライアンオークリー

1

最も簡単な手順:

  1. アプリにモデルフォルダーを作成します(フォルダー名はmodelである必要があります
  2. アプリディレクトリからmodel.pyファイルを削除します(削除中にファイルをバックアップします)
  3. そして、後に作成するのinitモデルフォルダ内の.pyファイルを
  4. そして、.pyファイルを初期化した後、単純な1行を書き込みます
  5. また、モデルフォルダにモデルファイルを作成した後、モデルファイル名はクラス名と同じである必要があります。クラス名が「Employee」の場合、モデルファイル名は「employee.py」のようになります。
  6. そして、モデルファイルで、model.pyファイルのように書き込むのと同じようにデータベーステーブルを定義します。
  7. それを保存

私のコード:django_adminlte.models.employeeからimport Employee

あなたのために:app_name.modelsから。model_file_name_only import 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.django2.xで発生します。
radtek

0

役に立つかもしれないスクリプトを書きました。

github.com/victorqribeiro/splitDjangoModels

モデルを適切な名前とインポートで個々のファイルに分割します。また、initファイルを作成して、すべてのモデルを一度にインポートできるようにします。

これが役立つかどうか教えてください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.