Python/Django — what is the difference between the

2020-04-28 03:56发布

I have a interesting Django problem.

Consider the following:

Model.objects.filter(Q(id='test1') and Q(id='test2'))

this returns the expected results, however

Model.objects.filter(Q(id='test1') & Q(id='test2'))

DOES NOT!!

What's going on here?

3条回答
神经病院院长
2楼-- · 2020-04-28 04:17

If you want Django ORM to return test1 and test2, you should use :

Model.objects.filter(Q(id='test1') | Q(id='test2'))

Model.objects.filter(Q(id='test1') & Q(id='test2')) means return model objects whose id is test1 while its is test2 at the same time. Of course, django will return an empty QuerySet.

and is a boolean operator in Python. For operation x and y the result is if x is false, then x, else y. Thus Q(id='test1') and Q(id='test2') equals Q(id='test1'), it is not what you want.

&/| is the the bitwise and/or operator.

BTW, there's no way to override the boolean operator, but you can override &/| operators in your class by define a method named __and__ / __or__.

below is the source code of the django Q object[github]:

class Q(tree.Node):
    """
    Encapsulates filters as objects that can then be combined logically (using
    & and |).
    """
    # Connection types
    AND = 'AND'
    OR = 'OR'
    default = AND

    def __or__(self, other):
        return self._combine(other, self.OR)

    def __and__(self, other):
        return self._combine(other, self.AND)
    ...
查看更多
爷的心禁止访问
3楼-- · 2020-04-28 04:19

according to the following tutorial

& is a Binary AND Operator copies a bit to the result if it exists in both operands.

Example: Assume if a = 60; and b = 13; Now in binary format they will be as follows:

a = 0011 1100

b = 0000 1101

(a & b) will give 12 which is 0000 1100

and Called Logical AND operator. If both the operands are true then then condition becomes true.

Example: (a and b) is true.

So the & was performing binary addition on your query set. Interesting.

查看更多
男人必须洒脱
4楼-- · 2020-04-28 04:29

I think you want OR here, and not AND

filters = ['test1', 'test2', 'test3', 'test4']
filtered = Model.objects.filter(Q(id = filters[0]))
for f in filters[1:]:
     subset = Model.objects.filter(Q(id = f))
     filtered = filtered | subset
查看更多
登录 后发表回答