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()

我将如何连接一个查询集,基本上将以下内容组合成一个 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')
4

2 回答 2

1

首先看看这个类似的问题是否对您有帮助:Using django how can I combine two queries from different 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
于 2012-04-08T01:56:07.760 回答
0

update

Just found How to combine 2 or more querysets in a Django view? , refs it for normal case


If the performance is critical and the result is used as an iterator, below is a simpler version of https://stackoverflow.com/a/313149/165603 in the link posted by 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

You could then

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)

For DB backends such as psycopg2, you may want to wrap querysets by using trick to reduce memory footprint.

You could also isolate code inside the while statement to make the merge function a general version. I used it to process large querysets sharing PK in practice, for example.

于 2012-04-08T09:06:44.350 回答