2009-06-27 7 views
3

モデルの継承が以下に定義されている方法で設定されているとします。Django ORMのスーパークラスモデルからサブベッドクラスのモデルにアクセスできますか?

class ArticleBase(models.Model): 
    title = models.CharField() 
    author = models.CharField() 

class Review(ArticleBase): 
    rating = models.IntegerField() 

class News(ArticleBase): 
    source = models.CharField() 

私は(この場合には、両方のレビューやニュース)タイプに関係なくタイトル順にすべての記事の一覧が必要な場合は、私はArticleBaseでクエリを実行することができます。どちらのモデルが私のレコードの外部キーを持っているかを調べることなく、ReviewまたはNewsレコードに関連するかどうかを判断するためにArticleBaseレコードを取得したら、簡単な方法はありますか?

答えて

1

私は、すべてのArticleBaseインスタンスがArticleBaseサブクラスのインスタンスであると仮定しています。

ArticleBaseにサブクラス名を格納する方法と、その情報に基づいてサブクラスまたはサブクラスオブジェクトを返すメソッドがあります。マルチテーブルの継承では、親インスタンスの子インスタンスにアクセスするためのプロパティが定義されているため、これはまったく簡単です。

これは決して唯一の方法ではありません。しかし、これはかなりシンプルで単純な解決策です。優れたcontribコンテンツタイプアプリとこれを活用する汎用モジュールは、一般的にこれを行うための豊富な方法を提供します。

ArticleBaseに次のように持っていることが有用であろう:(その場合には

def __unicode__(self) 
    return self.get_child().__unicode__() 

障害がサブクラスで__unicode__を定義することに注意してください、またはArticleBaseのインスタンスに__unicode__を呼び出していないものサブクラス化されていれば無限再帰につながる)。したがって、(例えば、ArticleBaseの直接的なインスタンス化を直接防止する)再健全性検査の下での勧告。

免責事項:このコードはテストされ

、私はそこにタイプミスや2を持っていると確信しているが、基本的な考え方は、健全でなければなりません。生産レベルのコードでは、使用エラーを傍受するための健全性のチェックが必要です。

1

ArticleBaseのサブクラスを知る必要はありません。 2つのサブクラス - これを適切に設計する - は同じメソッドを持ち、同じ意味で使用できます。

現在のところ、あなたの2つのサブクラスは多義的ではありません。それぞれ固有の属性を持っています。

80%のケースでは、お互いに関係がありません。これはうまくいきます。

「タイプに関係なくすべての記事」というフレーズは、自分が行っていることを説明する誤解を招く方法です。それはそれが実際よりも簡単に聞こえるようにします。

あなたが求めているのは、「ニュースとレビューの組合」です。私はあなたがこの組合で何をするのか分かりません。インデックスページが簡単に機能するためには、各サブクラスに書式設定の詳細を委任する必要があります。両方のサブクラスが実装するメソッドから、HTMLに優しい要約を発行する必要があります。この要約は、テンプレートが依存するものです。

class Review(ArticleBase): 
    rating = models.IntegerField() 
    def summary(self): 
     return '<span class="title">%s</span><span class="author">%s</span><span class="rating">%s</span>' % (self.title, self.author, self.rating) 

ニュースには、summaryの方法が必要です。

次に、これらの2つの互いに素な型を結合して、単一のインデックスを生成できます。

+0

データベースではなくメモリで実行する必要がある、日付順に並べ替えるときに複雑さが増します。しかし私の例は実際に私はブログ、ニュース、レビュー、バイヤーのガイド、ギャラリーを扱っている単純化されています。私はちょうど最新のオブジェクトのリストをタイトル、URL、作者とともに持っていなければなりません。 –

+0

@Jason Christa:正しい。しかし、このユースケース(すべてのユニオン)はしばしば稀です。ユニオンがまれなユースケースでない場合は、間違ったモデルがあります。ユニオンが一般的な必要性がある場合は、多数のヌル入力可能なフィールドを持つ単一のテーブルを持つ必要があります。 –

0

あまり洗練されていない現実的なアプローチは、article_typeフィールドを持つ単一のモデルを持つことです。すべての記事を扱う方がはるかに簡単で、ニュースとレビューのクエリセットから離れた単純なフィルタ節です。

私はこの問題やそれが問題となるかもしれないシナリオに対する議論を聞くことに興味があります。私はこれをさまざまな時代に継承してきましたが、最高のテクニックについて明確な結論に至っていません。

+0

1つのテーブルに対する短所は無駄なスペースであり、後で新しい記事タイプを追加するのは難しく、すべてのタイプには適用されない必須フィールドを強制するのが難しく、単一のタイプに対してのみクエリを実行し、 SQLのこの問題を解決するには、UNION(SELECT ...)、(SELECT ...)、(SELECT ...)ORDER BY dateを実行します。 –

+0

Django ORMでUNIONをサポートしていない場合は、カスタムSQLを使用するか、またはPythonを使用してクエリーセットに参加(およびおそらくフィルタリング)する必要があります。 アプリケーションによっては、上記の欠点よりもコストがかかる可能性があります。私はそれがトリッキーなケースだと思うし、特定の要件に依存するかもしれません - あなたはそれらを別々に扱う必要があるよりも頻繁に同じ2つのモデルを扱う必要がありますか? パフォーマンス、RAM、ディスク容量、可読性を最適化する必要がありますか? –

0

https://docs.djangoproject.com/en/dev/topics/db/models/#multi-table-inheritance

あなたは明示的クエリにデータベースを持っていない、あなたはこのレビューのインスタンスを返すか、例外を送出するか

article_base_instance.review 

を行うことができます。残りのサブクラスでも同じです。

あなたが唯一のオプションであるMTIを使用している場合。 :)

関連する問題