web-dev-qa-db-ja.com

models.pyが巨大になった場合、それを分割する最良の方法は何ですか?

上司からの指示:「models.pyにロジックを入れないようにします。これ以降、データベースにアクセスするためのクラスとしてのみ使用し、モデルクラスを使用する外部クラスにすべてのロジックを保持します。またはそれらを包みます。」

これは間違った方法だと思います。ファイルを小さく保つためだけにモデルのロジックを除外することは悪い考えだと思います。ロジックがモデルで最も優れている場合は、ファイルサイズに関係なく、ロジックが実際に適用されます。

インクルードを使用する簡単な方法はありますか? PHPの話では、他の場所からのモデルクラスがmodels.py include()しかないことをスーパーバイザーに提案したいと思います。概念的には、これによりモデルに必要なすべてのロジックを持たせることができますが、ファイル数を増やすことでファイルサイズを抑えることができます(これにより、競合などのリビジョン管理の問題が減少します)。

それで、models.pyファイルからモデルクラスを削除する簡単な方法がありますが、モデルはすべてのDjangoツールで動作しますか?または、完全に異なるまだエレガントなソリューションがありますか? 「大きな」models.pyファイルの一般的な問題に?どんな入力もいただければ幸いです。

87
Eddified

Djangoは、1つの大きなアプリケーションではなく、多数の小さなアプリケーションを構築できるように設計されています。

すべての大きなアプリケーションの内部には、多くの小さなアプリケーションが無料になるのに苦労しています。

もしあなたの models.py大きく感じています。あなたはやりすぎです。やめる。リラックス。分解する。

小さく、再利用できる可能性のある小さなアプリケーションコンポーネントまたは断片を見つけます。 実際にそれらを再利用する必要はありません。それらを潜在的に再利用可能であると考えてください。

アップグレードパスを検討し、いつか置き換えたいアプリケーションを分解します。 実際にを置き換える必要はありませんが、将来、よりクールなものに置き換えられる可能性がある、プログラミングのスタンドアロンの「モジュール」と見なすことができます。

約12のアプリケーションがあり、それぞれmodel.pyは、約400行以下のコードです。それらはすべて、約6ダース未満の個別のクラス定義にかなり集中しています。 (これらは厳密な制限ではなく、コードに関する観察結果です。)

私達は早くそして頻繁に分解します。

63
S.Lott

モデルクラスがモデルを操作するメソッドを含むのは自然なことです。メソッドがbook.get_noun_count()のBookモデルがある場合、それが属します。メソッドが実際に本質的に属しているのでない限り、 "get_noun_count(book)"と記述する必要はありません。他のいくつかのパッケージ。 (たとえば、「get_Amazon_product_id(book)」を使用してAmazonのAPIにアクセスするためのパッケージがある場合)。

Djangoのドキュメントでモデルを単一のファイルに配置するよう提案されたとき、私はしつこくなり、適切なサブパッケージに分割する方法を最初から理解するのに数分かかりました。

site/models/__init__.py
site/models/book.py

__init__.pyは次のようになります。

from .book import Book

「site.modelsインポートブックから」と書くことができます。


以下は、Django 1.7より前のバージョンにのみ必要です。 https://code.djangoproject.com/ticket/3591 を参照してください)

唯一のトリックは、Djangoのバグのため、各モデルのアプリケーションを明示的に設定する必要があるということです。アプリケーション名は、モデルパスの最後から3番目のエントリであると想定しています。 "site.models.Book"は "site"になりますが、これは正しいです。 「site.models.book.Book」は、アプリケーション名が「モデル」であると考えさせます。これはDjangoにとってかなり厄介なハックです。インストールされているアプリケーションのリストでプレフィックスの一致を検索する必要があります。

class Book(models.Model):
    class Meta: app_label = "site"

基本クラスまたはメタクラスを使用してこれを一般化することもできますが、まだ気にしていません。

104
Glenn Maynard

あなたが持つ可能性のある多くの問題のどれがどれなのか、私にはまったくわかりません。ここに答えのいくつかの可能性があります:

  • 同じファイル内の複数のモデル

    それらを別々のファイルに入れます。依存関係がある場合は、インポートを使用して追加のモデルを取得します。

  • models.pyの無関係なロジック/ユーティリティ関数

    追加のロジックを個別のファイルに入れます。

  • データベースからいくつかのモデルインスタンスを選択するための静的メソッド

    別のファイルに新しい Manager を作成します。

  • モデルに明らかに関連するメソッド

    save、__ unicode __、get_absolute_urlはその例です。

4
hughdbrown