Djangoのアプリケーションで、models.pyのコード量が多くなってきたので、複数のファイルに分割する話。
ハマりどころがあるので書いておく。試したのはPython2.7、Django1.4。
testapp/ __init__.py models.py
models.py
from django.db import models class Foo(models.Model): value = models.IntegerField() class Bar(models.Model): value = models.IntegerField()
modelsをディレクトリにする
まず、models.pyと同じディレクトリ階層にmodelsディレクトリを作成し、__init__.pyとmodels.pyを分割したものを置く
testapp/ __init__.py models/ __init__.py foo.py bar.py
foo.py
from django.db import models class Foo(models.Model): value = models.IntegerField()
bar.py
from django.db import models class Bar(models.Model): value = models.IntegerField()
これだけでは、syncdbコマンドなどでモデルが認識されない。
__init__.pyの編集
syncdbコマンドなどでは、{アプリケーション名}.modelsのような名前のモジュールからModelクラスを継承したクラスを探している。つまり models/__init__.py で分割した各モジュールのモデルをインポートするようにすればよい。
__init__.py
from testapp.models.foo import Foo from testapp.models.bar import Bar
さて、これで問題ないかと思いきや、もう一点変更しないとsyncdbで認識されない。
Meta.app_labelの変更
モデルが所属するアプリケーションの名前をapp_labelで設定する必要がある。app_labelを設定しない場合は、モデルが定義されたモジュールの1つ上の階層のモジュール名になる。
syncdbなどの際に、アプリケーション名とapp_labelが一致しないものは認識されない。
foo.py
from django.db import models class Foo(models.Model): value = models.IntegerField() class Meta: app_label = 'testapp'
bar.py
from django.db import models class Bar(models.Model): value = models.IntegerField() class Meta: app_label = 'testapp'
以上でsyncdbなどで認識される状態でmodelsを複数ファイルに分割できる。