29

2 回目の Django チュートリアルの作業を終えたばかりで、物事をより明確に理解できるようになりました。ただし、サイト内のアプリが互いにどのように相互作用するかはまだ不明です。

たとえば、私がブログ アプリケーションを書いているとしましょう (かなり人気のあるアクティビティのようです)。ブログの投稿とコメントは一緒になる傾向がありますが、Djano 開発の一般的な哲学と同様に、それらは別個のアプリに組み込む必要があるほど十分に明確です。

次の例を考えてみましょう。実際には、コメント アプリを自分で実際に作成することはありません。適切なコードが Web 上に既に存在するためですが、これはデモンストレーション/練習用です。

mysite/blog/models.py

from django.db import models

class post(models.Model):
    title = models.CharField(max_length=200)
    author = models.CharField(max_length=200)
    content = models.TextField()

mysite/comments/models.py

from django.db import models
from mysite.blog.models import post

class comment(models.Model):
    id = models.AutoField()
    post = models.ForeignKey(post)
    author = models.CharField(max_length=200)
    text = models.TextField()

上で書いた、別のアプリからモデルをインポートして外部キーとして設定すると、Django アプリはどのようにやり取りするのでしょうか? または、サイトを構成するアプリが対話するための別の/より良い方法はありますか?

更新
ある回答の推奨に従って、contrib.contenttypes のドキュメントを読んでいます。これを正しく読んでいれば、サンプル コメント アプリを次のように書き直すことができます。

from django.db import models  
from django.contrib.contenttypes.models import ContentType
from django.contrib.contentypes import generic

class comment(models.Model):  
    id = models.AutoField()  
    author = models.CharField(max_length=200)  
    text = models.TextField()  
    content_type = models.ForeignKey(ContentType)  
    content_object = generic.GenericForeignKey(content_type, id)  

これは正しいでしょうか?

4

4 に答える 4

22

django の組み込みcontenttypes フレームワークを見てみましょう:

django.contrib.contenttypes

アプリケーションをスタンドアロン ユニットとして開発できます。これは、django 開発者が、django の組み込みコメント フレームワークがプロジェクト内の任意のモデルにコメントを添付できるようにするために使用したものです。

たとえば、各ユーザーがブログ投稿、画像、またはユーザー プロファイルに「お気に入り」のスターを残すことを許可するなど、さまざまなタイプの他のコンテンツ オブジェクトに「添付」したいコンテンツ オブジェクトがある場合、次のような一般的な関係フィールドFavoriteを持つモデル:

from django.db import models
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic

class Favorite(models.Model):
    user = models.ForeignKey(User)
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')

このようにFavoriteして、任意のユーザーからスターをプロジェクト内の任意のモデルに追加できます。受信者モデル クラスを介して API アクセスを追加する場合は、受信者モデルにリバース ジェネリック リレーション フィールドを追加するか (ただし、これは 2 つのモデルを「結合」することになりますが、これは回避したいと言いました)、またはルックアップを行うことができます。および受信者インスタンスのFavoriteモデルを介して、例については公式ドキュメントを参照してください。content_typeobject_id

于 2008-12-09T18:01:25.200 に答える
4

「上で書いた、別のアプリからモデルをインポートして外部キーとして設定すると、Django アプリはどのようにやり取りするのですか?」

うん。私のために働きます。

相互に借用する約 10 個のアプリケーションがあります。

これにより、単体テスト スクリプトに一種の依存関係が生じます。

このように見えます。

  • "所有"。他のアプリケーションが依存するコア所有権の概念を定義する単純なデータ所有権アプリケーションがあります。ここにはいくつかの簡単な表があります。

  • "もの"。【本名ではありません】。私たちの Thing アプリケーションには、さまざまなユーザー グループが所有するデータ要素があります。このアプリのモデルには、実際にはいくつかの複雑なテーブルがあります。それは「所有権」に依存します。

  • 「テーブル」。【本名ではありません】。一部のユーザーは、かなり複雑なオフライン モデル (おそらくスプレッドシートを使用) を作成し、そのモデリングの結果を「テーブル」にアップロードします。これには、かなり複雑なテーブルのクラスターがあります。それは「所有権」に依存します。

  • "結果"。【本名ではありません】。私たちの結果は、所有者を持つものに基づいています。結果はモノとテーブルに基づいており、顧客の要求に対する応答です。これはそれほど複雑ではなく、おそらく 2 つまたは 3 つのコア テーブルだけです。それは「モノ」と「テーブル」に依存します。いいえ、完全にスタンドアロンではありません。ただし、それが依存する他のものよりも多くの変更を受ける可能性があります。というわけで別物です。

  • "処理"。大きなバッチ ジョブをスケジュールし、監視します。これは、このアプリケーションにあります。これは非常に一般的で、さまざまな方法で使用できます。完全に自立します。

  • "ようこそ"。ほとんど静的なページの束を表示する「ようこそ」アプリがあります。これにはテーブルが多すぎません。しかし、最初の化身は複雑すぎたため、2 番目の化身です。完全に自立します。

依存アプリ間の唯一の関係は、いくつかのテーブル名です。これらのテーブル (およびそのキー) を保持している限り、必要に応じて他のアプリを再配置できます。

于 2008-12-09T18:06:38.637 に答える
3

一部のアプリを別のアプリに依存させることに問題はありません(imho)。結局のところ、アプリは一連のモデルに対する操作にすぎません。どのアプリがどのアプリに依存しているかを常に認識しておく必要があります (これを依存関係マップと呼ぶことができると思います)。

contenttypes フレームワークとの疎結合を実現できます。これにより、アプリを真にポータブル/プラグ可能にしつつ、他のアプリケーションと統合することができます。

私はコメント アプリを作成しました (そうです、ホイールを再発明しました)。このアプリは、他のアプリケーションに統合できます。コメントを投稿するページのテンプレートに数行を追加します (カスタム タグを使用)。

モデル「スレッド」を他のモデルにプラグイン可能にしたいとします。アイデアは、一般的な外部キーを作成し(それについてはdjangoのドキュメントを参照)、任意のオブジェクトを受け取り、それに対応する「スレッド」を返す(または必要に応じて作成する)小さな関数を作成し、カスタムテンプレートタグを作成することです。その機能を使用します{% get_thread for arbitrary_object as thread %}。すべての投稿は、任意のタイプのオブジェクトに関連するスレッドに関連しています。

「スレッド」オブジェクトは一種のプロキシと考えることができます。投稿を特定の「記事」または「ブログ投稿」に関連付ける代わりに、ある意味で抽象的なスレッドに関連付けるだけです。 、スレッドとはですか? 単なる投稿の集まりです。次に、スレッドは、そのタイプに関係なく、任意のオブジェクトに関連付けることができます。(それ以上のことを行いますが、anon.投稿の許可/禁止、ページ上のコメントのクローズ/オープンなどの追加情報を保持できます..)

編集

コンテンツ タイプ フレームワークを使用して一般的な外部キーを作成する方法は次のとおりです。

from django.contrib.contenttypes import generic
from django.contrib.contenttypes.models import ContentType

class Thread( models.Model ):
    object_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    object = generic.GenericForeignKey('object_type', 'object_id')

django がすべてのオブジェクトの実装を想定している暗黙の「共通」インターフェースを利用することで、より「透過的」にすることができます。

    #inside the Thread class:
    def __unicode__(self):
        return unicode(self.object)
    def get_absolute_url(self):
        return self.object.get_absolute_url()
于 2008-12-09T18:35:09.047 に答える
2

あなたのコードは正しいようです。ただし、投稿とコメントはブログアプリに保持します。これが Djangoの流儀であると言っているわけではありませんが、これらのモデルは同じアプリに入れるのに十分近いものです。

プロジェクトの分割方法

次の場合、アプリを分離します。

  • 再利用できるように設計する予定です。(そして疎結合を試してください)
  • (大規模なプロジェクトの場合) プロジェクトの主要なセクションで構成されます。

一方で; 多くの小さなアプリ (単一のモデルと 2 つのビューを備えたアプリなど) を使用すると、読み取りと保守が困難になります。

アプリがどのように相互作用するか

これは、プロジェクトの種類とアプリの種類によって異なります。たとえば、アプリが別のアプリに暗黙的に依存している (つまり、汎用的ではない) 場合、他のアプリからの参照をインポートして使用することは許容されます。この場合、2 番目のアプリは単独でインストールされる可能性がありますが、最初のアプリには 2 番目のアプリが必要です。

コメント アプリなど、再利用性が高く汎用的なアプリを作成する場合は、何らかのセットアップ メカニズムを統合する必要がある場合があります。おそらく、いくつかの新しい設定や追加の URL 構成、またはモデルの特別なディレクティブ/メソッド...django.contrib.adminは、この良い例です。

ただし、必要でない限り、アプリは対話すべきではありません。不要な結合を避けるようにアプリを設計することは非常に便利です。これにより、アプリの柔軟性が向上し、保守が容易になります (ただし、統合のコストが高くなる可能性があります)。

于 2008-12-09T17:45:34.750 に答える