3

in my database there is a table that holds some user information. The table is called UserBalance and fields include user, credits_in and credits_out and remark (among others)

I am trying to sum the credits_in for a certain user but I get different sums for different cases. Take a look at this:

>>> cg = UserBalance.objects.filter(user=ranked_user).filter(remark__icontains='credits g').aggregate(sum_in=Sum('credits_in'))
>>> cg
{'sum_in': 35.85}
>>> cg = UserBalance.objects.filter(user=ranked_user).filter(Q(remark='credits gained') or Q(remark='credits given')).aggregate(sum_in=Sum('credits_in'))
>>> cg
{'sum_in': 26.16}
>>> cg = UserBalance.objects.filter(user=ranked_user).filter(Q(remark='credits given') or Q(remark='credits gained')).aggregate(sum_in=Sum('credits_in'))
>>> cg
{'sum_in': 9.69}

in the first case I used i_cointains, in the second and third cases I use a Q() but with its terms switched.

Can someone explain what is the difference between the 2nd and the 3rd case?

Tomasz Jakub Rup
  • 10,502
  • 7
  • 48
  • 49
xpanta
  • 8,124
  • 15
  • 60
  • 104

1 Answers1

4

You should use (Q(remark='credits gained')|Q(remark='credits given')), not(Q(remark='credits gained') or Q(remark='credits given'))

It's 2 completely different operators: | is bitwise OR, but it's overriden for Q():

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

while or is logical (or rather 'coalescing') operator. It means that Q(remark='credits gained') or Q(remark='credits given') will return first not-None object, that's why in your second case it will result in Q(remark='credits gained'), and in the third one - in Q(remark='credits given')

Kirill Bubochkin
  • 5,868
  • 2
  • 31
  • 50