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


91

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

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

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

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


7
あなたはインポートステートメントを知っていますか?
balpha 2009

7
PS。私はそれを攻撃的にするつもりはありません、私はあなたがどこにいるのか知りたいだけです。
balpha 2009

1
はい、しかし私はdjangoの管理ツールがモデルを取り込むためにimportステートメントを使用するだけで機能するかどうか知りませんでした。djangoのツールがうまく機能しないことを確認するためだけにプレーンOLEインポートを使用するのに多くの時間を費やすよりも、ここで質問したいと思います。私はpythonとdjangoの方が新しいことを認めているので、おそらくimportステートメントを単純に理解しているだけです...
2009

回答:


64

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

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

models.py気分が良ければ、やりすぎです。やめる。リラックス。分解する。

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

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

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

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


1
その場で。重要なWebアプリケーションは、いくつかの小さな「アプリ」になります。コントリビュートやその他の人気のあるアプリのヒントを取る、ユーザー認証は1つのアプリ、タグ付けは別のアプリ、ユーザープロファイルはもう1
Javier

4
これは「正しい」方法であり、知っておくと役立ちますが、私が探していたものとはまったく異なります。どのような答えを探していたのかわからない場合は、お詫び申し上げます。:)
2009

@Eddified:これを行わないと、悪化するだけです。今すぐ分割を開始してください。
S.Lott、2009

おかしなことに、この瞬間に私はJacob Kaplan Moss(OSCONで)がこれを非常に強く正当化された詳細で正確に説明しているのを聞いています;-)。
Alex Martelli

13
グレン・メイナードの答えは、これではるかに優れています。複雑なWebアプリを多数のアプリに分割することは確かに良い習慣ですが、model.pyファイルをアプリ内でリファクタリングすることも同様です。2つのアクションは直交させることができます。
エリック

108

モデルクラスがモデルを操作するメソッドを含むのは自然なことです。メソッドを持つBookモデルがある場合book.get_noun_count()、それが属し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"

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


2
+1私はこれを成功させました。S. Lottは複数のアプリに適していますが、これが現在のソリューションです。
Alexander Ljungberg、

35
モデルが密接に本質的に関連している場合、物事を一連のアプリに分割することのメリットはあまりありません。
グレンメイナード

2
これは私に興味があります。私が投稿したdjango wikiリンクscomptを読んだところ、「これは、現在のメインブランチで、メタクラスapp_labelsなしで動作することが確認されています。」つまり、メインブランチで作業している場合、Meta:app_labelのものを破棄できるということですか。この問題を解決するためのチケットに関するコメントの後であるので、混乱します。
Dan.StackOverflow 2009

2
トランクでテストしました(今日の初めの時点では、r11286)。app_nameが設定されていない場合、モデルは単に「sqlall appname」に表示されず、おそらくsyncdbによって作成されません(ただし、私はそれを使用しないため、テストできません)。エラーを引き起こさないので、これはかなり紛らわしいエラーケースです。静かに表示されません。
グレンメイナード

2
うわー、ほぼ10年後、私はまだこのソリューションが大好きです。これは、コードを小さなアプリに分割するよりもはるかに優れたアプローチであることに同意しました。私の意見では、コードベースを推論することは困難です。
マイケルヘイズ

5

私はあなたが持つ可能性のある多くの問題のうちどれを取得するのか全く理解できません。ここに答えのいくつかの可能性があります:

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

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

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

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

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

    別のファイルに新しいマネージャーを作成します。

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

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

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