2012-04-08 12 views
2

私は、次の2つのモデルがあります:私は基本的に1 QSに次のように組み合わせて、クエリセットを連結する方法をを連結2つのクエリセット

class JobPosition(models.Model): 
    job = models.ForeignKey(Job, related_name='positions') 
    position = models.ForeignKey('userprofile.Position') 
    date_added = models.DateTimeField() 
    end_date = models.DateTimeField() 

class ExternalJob(models.Model): 
    name = models.CharField(max_length=256) 
    position = models.ForeignKey('userprofile.Position') 
    date_added = models.DateTimeField() 
    end_date = models.DateTimeField() 

を?

internal_jobs = JobPosition.objects.filter(end_date__gte=datetime.now()) 
external_jobs = ExternalJob.objects.filter(end_date__gte=datetime.now()) 
all_jobs = (internal_jobs + external_jobs).order_by('-date_added') 

答えて

1

まず、この類似の質問があなたに役立つかどうかを確認してください:Using django how can I combine two queries from separate models into one query?これは、別のSQL文を追加するために行うべきアプローチかもしれません(ただし、SQL側で尋ねていることを実行できるかどうかはわかりません)

達成したいのは、怠惰な評価これらの二つのクエリセットの組み合わせ、あなたはitertools.chain使用することができます。

from itertools import chain 

combined = chain(internal_jobs, external_jobs) 
# combined is a generator that will iterate over your combined 
# iteratables 
for result in combined: 
    # do something 

私は、最終的な日付の並べ替えのために、あなたはクライアント側でこれをしなければならないかもしれないと思います。 sortedコールを実行すると、完全なクエリーセットリストが評価されます。

from operator import attrgetter 

combined = chain(internal_jobs, external_jobs) 
for result in sorted(combined, key=attrgetter("date_added"), reverse=True): 
    # do something 
0

更新

パフォーマンスが重要であり、結果はイテレータとして使用されている場合は、単に以下、How to combine 2 or more querysets in a Django view?、通常の場合のために、参考文献を


を発見したの簡単なバージョンでありますリンクのhttps://stackoverflow.com/a/313149/165603は、jdi

def merge_by_latest_date_added(*querysets): 
    querysets = [[qs, None] for qs in querysets] 

    def iterator_helper(): 
     for qs_v in querysets[:]: 
      qs, v = qs_v 
      if v is not None: 
       continue 
      try: 
       qs_v[1] = qs.next() 
      except StopIteration: 
       querysets.remove(qs_v) 
     return querysets 

    while iterator_helper(): 
     qs_v = max(querysets, key=lambda x:x[1].date_added) 
     yield qs_v[1] 
     qs_v[1] = None 

その後、

internal_jobs = internal_jobs.order_by('-date_added').iterator() 
external_jobs = externals_jobs.order_by('-date_added').iterator() 
all_jobs = merge_by_latest_date_added(internal_jobs, external_jobs) 

などpsycopg2などのDBバックエンドの場合、あなたはメモリフットプリントを削減するためにusing trickでクエリセットをラップすることをお勧めします可能性があります。

whileステートメント内でコードを分離して、マージ機能を一般バージョンにすることもできます。私は実際にPKを共有する大きなクエリーセットを処理するためにこれを使用しました。

関連する問題