开发者

simple way for QuerySet union and subtraction in django?

Consider two QuerySet objects of the same class. Is there a simple way to unify them into a single QuerySet by calculating 开发者_如何学Gothe union? Also, is there a simple way to subtract them? Removing all elements that appear in both sets from one of the sets?


Since Django 1.11, QuerySets have union(), intersection() and difference() methods.

It's also possible to use & and | infix operators with QuerySets (I could not find a reference to this in the docs, so I guess union() and intersection() is the preferred way to combine two querysets.

qs3 = qs1.union(qs2)         # or qs3 = qs1 | qs2
qs3 = qs1.intersection(qs2)  # or qs3 = qs1 & qs2
qs3 = qs1.difference(qs2)    # no operator for this

You can also use Q() objects which like QuerySets implement | and &, and additionally the invert prefix operator ~.

Neither class implement the xor / symmetric difference infix operator ^.


Subtract a QuerySet from another QuerySet using the same model.

This works - but is probably slowly

queryset_with_hello = Blog.objects.filter(name__icontains='hello')
queryset_without_hello = Blog.objects.exclude(pk__in=queryset_with_hello)

Read the performance considerations in django documentation:

https://docs.djangoproject.com/en/dev/ref/models/querysets/#in


Going back to django's documentation, you can:

new_query_set = query_set_1 | query_set_2

This works as a logical OR which is actually addition without duplicates. This answers the addition aspect and AFAIK does not hit the db at all!

new_query_set = query_set_1 & query_set_2

This works as a logical AND.

Still missing how to subtract QuerySets. It's hard for me to believe this has not been dealt with elegantly by the community...


You can use the Q object.

The syntax could be something like this:

added_query_set = YourModel.objects.\
         filter(Q(id__in=old_query_set_1)|Q(id__in=old_query_set_2))

You probably can optimize based on your actual needs and get the amount of db hits down (right now it's 3), but this should get you started.


I think for operations as this you need to evalute them. So you can call list() on them and work on them with the common python list operations!


qs3 = qs1.union(qs2) # union
qs4 = qs1.difference(qs2) # subtraction
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜