2012-04-08 95 views
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() 

我將如何串聯一個QuerySet,基本上將下述成一個QS?

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) 

對於DB的後端,比如psycopg2,您可能希望通過using trick包裹查詢集,以減少內存佔用。

您也可以在while語句中隔離代碼,以使合併功能的普通版本。例如,我用它來處理在實踐中共享PK的大型查詢集。