1

私が質問に答えるのを助けるためにこの投稿をすべて読む必要はありません。この投稿の残りの部分は質問が来た文脈だけですが、一般的な質問は次のとおりです。

Djangoの複数のモデルにまたがるビジネスロジックをどこに配置しますか?

いくつかの可能性:

  • いくつかのビュー?(私はそうは思いません、それは管理者といくつかのビューで動作する必要があります、DRY)
  • モデル/フォームにメソッドを保存しますか?(方法?)
  • モデル/フォームのメトスをきれいにしますか?(どのように?)
  • ロジックを分割して信号を使用しますか?(どのように?)
  • 他の?

コンテクスト:

私はこのモデルを持っています:

  1. 部門:会社のさまざまな部門を参照します(リスク、財務、IT、...)
  2. 従業員:一定期間、1つの部門にのみ所属し、その後他の部門に異動する場合があります。
  3. プロジェクト:各部門は複数のプロジェクトを持つことができ、プロジェクトは複数の部門に属しています。
  4. メンバーシップ:join_dateやleave_dateなどの他のフィールドを含む、従業員と部門の多対多関係の中間テーブル。重要なフィールドはfk:Department、fk:Employeeです。
  5. 履歴:メンバーシップとプロジェクトの中間テーブル。どの従業員がウィッシュプロジェクトに関与していて、ある部門で働いていたのかを教えてくれます。重要なフィールドはfk:Membership、fk:Projectです。
  6. CurrentProjects:部門と現在取り組んでいるプロジェクトを関連付けるテーブル。

私がDjango管理者で、リスク部門に行き、リスクには現在Project1とProject2が割り当てられているとします。新しい従業員「JhonSmith」を追加し(たとえば、Departmentでインラインフォームを使用して)、保存ボタンを押すと、モデルの履歴が次の情報で更新されます。

メンバーシップテーブル(重要なフィールドのみ):

pk部門の従業員join_dateleave_date
20リスクジョンスミスxxxxxxxx


履歴テーブル(重要なフィールドのみ):

メンバーシッププロジェクト
20プロジェクト1
20プロジェクト2

つまり、新しい従業員が新しい部門に割り当てられるとき、その部門からのすべての実際のプロジェクトは、テーブル履歴のそのメンバーシップ従業員部門に割り当てられる必要があります。

問題は、このロジックをDjangoのどこに配置するかです。このロジックには複数のモデルが含まれていることがわかるように、いくつかの可能性は次のとおりです。

  • いくつかの見方では(私はそうは思わないが、それは管理者間期および他の場所で機能しなければならない)
  • メンバーシップ、部門、または従業員のモデル/フォームのクリーンな方法では?
  • メンバーシップ、部門、または従業員のモデル/フォームの保存方法では?
  • ロジックを分割してシグナルのようなものを使用する必要がありますか?(いくつかの例?)
  • その他?
  • 私はすべてを複雑にしすぎていますか?=)

考慮事項:コードがプロセスの任意の時点でvalueerrorを生成し、ユーザー/管理者がこのエラーを無制限の形式で確認できると便利です。

4

2 に答える 2

3

ロジックがどこにあるべきかという側面についてコメントしているだけです。これはすべて、私にはモデルロジックのように聞こえます。DjangoにはMVCの概念が少し混ざっています。その純粋なデータ関係の場合、私はそのすべてのモデルロジックを信じています。メソッドを影響を受けるモデルにできるだけ近づけて、トリガーモデルから可能な限り最小の呼び出しを行うことをお勧めします。

アプリの分離に非常に関心がある場合は、シグナルを使用できます。モデルAは、保存中にXYZを呼び出す必要があることを知っているのではなく、逆の方向に進みます。モデルAは信号を発するだけです。XYZは信号への接続を担当します。完全に一般的なプロジェクトアプリでシグナル定義を作成することもできます。その場合、トリガーモデルと受信モデルのどちらも互いのアクションを認識しません。それはそれらをバインドするだけです。

モデルの保存の前後など、いくつかの組み込みシグナルがあります。つまり、保存トリガーを探している場合は、カスタムを発行する必要はありません。しかし、あるモデルロジックのさまざまな時点で、「名前が変更されました」などのカスタム信号を出力する必要があるとしましょう。独自の信号を出力できます。

モデルA

import django.dispatch

name_changed = django.dispatch.Signal(providing_args=["name"])

class ModelA:
    ...

    def foo:
        # something happened here
        name_changed.send(sender=self, name=the_name)

モデルB、C、D

from myApp.modelA import name_changed

name_changed.connect(modelB.handle_name_change, dispatch_uid="my_unique_identifier")
name_changed.connect(modelC.handle_name_change, dispatch_uid="my_unique_identifier")
name_changed.connect(modelD.handle_name_change, dispatch_uid="my_unique_identifier")

個人的には、一般的な「コントローラーモデル」ロジックを必要とするアプリ用にutils.pyモジュールを作成する習慣があります。彼らはアクションやヘルパーのようなものです。

于 2012-07-07T21:47:48.900 に答える
0

おそらく問題は、そこにある「履歴」テーブルです。Projectあなたがあなたのテーブルにどんな種類の情報を持っているのか分かりません。ただし、すべてのプロジェクトに開始日と終了日がある場合、履歴テーブルは重複する情報を処理しています。この場合、どのプロジェクトで従業員が働いたかを知りたい場合は、この従業員がその部門で働いた日付の範囲を知る必要があります。次に、その部門のプロジェクト間で開発されたプロジェクトを見つける必要があります。以前の日付範囲。

私の主張をご理解いただければ幸いです。いいえの場合は、私がそれをよりよく説明できるように教えてください(おそらく例を使って)。

しかし、私はあなたの問題とモデルを理解しているので、その履歴テーブルは必要ないと思います。情報が重複します...

したがって、Projectモデルにこの情報(日付の範囲)がある場合、ソリューションはマネージャーに存在する必要があります。これは、複数のテーブルに存在する必要のある情報を見つけるだけの問題だからです...

それが役に立てば幸い!

于 2012-07-07T21:48:44.117 に答える