12

私の特定のケースでは、取得してページ付けする必要がある 2 種類の「メッセージ」があります。

詳細は省き、最初の種類は Msg1 と呼ばれるモデルにあり、もう 1 つは Msg2 と呼ばれるモデルにあるとだけ言っておきましょう。

これら 2 つのモデルのフィールドは完全に異なります。2 つのモデルに共通するフィールドは、"date" と "title" (そしてもちろん id) だけです。

取得できますがMsg1.objects.all()Msg2.objects.all()これら 2 つのクエリを 1 つのクエリに結合し、日付で並べ替えて、ページ番号を付けることはできますか?

クエリの怠惰な性質を維持する必要があります。

簡単な解決策は、list(query)両方のクエリを実行し、それらを python リストに結合することです。しかし、これは明らかな理由で非効率的です。

モデルと dp-api の django リファレンスを調べましたが、異なるモデル/テーブルのクエリを 1 つに結合する方法はないようです。

4

2 に答える 2

11

Model inheritanceを使用することをお勧めします。

日付とタイトルを含む基本モデルを作成します。説明に従って、Msg1 と Msg2 をサブクラス化します。基本モデルを使用して (ページを埋めるための) すべてのクエリを実行し、最後に派生型に切り替えます。

継承の本当に優れた点は、django を使用すると、他のモデルの外部キーで基本モデルを使用できるため、アプリケーション全体をより柔軟にすることができることです。ボンネットの下では、1 対 1 のキーを含むサブモデルごとのテーブルを持つベース モデルの単なるテーブルです。

于 2008-11-24T00:35:42.353 に答える
2

「これらの 2 つのクエリを 1 つのクエリに結合し、日付で並べ替えて、ページ番号を付けますか?」

  1. それが SQL ユニオンです。Django ORM を離れて、SQL ユニオンを使用します。SQL はソートする一時的な結果を作成する必要があるため、それほど高速ではありません。

  2. ソート可能な一時的な結果を作成します。リストにはソート方法があるため、2 つの結果を 1 つのリストにマージする必要があります。

  3. 結果をページ分割して、2 つのクエリ セットを受け入れるマージ アルゴリズムを作成します。


編集。これがマージアルゴリズムです。

def merge( qs1, qs2 ):
    iqs1= iter(qs1)
    iqs2= iter(qs2)
    k1= iqs1.next()
    k2= iqs2.next()
    k1_data, k2_data = True, True
    while k1_data or k2_data:
        if not k2_data:
            yield k1
            try:
                k1= iqs1.next()
            except StopIteration:
                k1_data= False
        elif not k1_data:
            yield k2
            try:
                k2= iqs2.next()
            except StopIteration:
                k2_data= False
        elif k1.key <= k2.key:
            yield k1
            try:
                k1= iqs1.next()
            except StopIteration:
                k1_data= False
        elif k2.key < k1.key: # or define __cmp__.
            yield k2
            try:
                k2= iqs2.next()
            except StopIteration:
                k2_data= False
        else:
            raise Exception( "Wow..." )

ページネーションで折りたたむことができます:

def paginate( qs1, qs2, start=0, size=20 ):
    count= 0
    for row in merge( qs1, qs2 ):
        if start <= count < start+size:
            yield row
        count += 1
        if count == start+size:
            break
于 2008-11-24T00:10:39.423 に答える