连接两个查询集
问题描述:
我有以下两种模式:连接两个查询集
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')
答
首先看看这个相似的问题是否会帮助到您: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
答
更新
刚刚发现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的大型查询集。