14👍
✅
You could add an __xor__()
method to Q that uses and/or/not to do the XOR logic.
from django.db.models import Q
class QQ:
def __xor__(self, other):
not_self = self.clone()
not_other = other.clone()
not_self.negate()
not_other.negate()
x = self & not_other
y = not_self & other
return x | y
Q.__bases__ += (QQ, )
After doing this I was able to Q(...) ^ Q(...)
in a filter()
call.
Foobar.objects.filter(Q(blah=1) ^ Q(bar=2))
Which means the original attempt no longer throws an unsupported operand exception.
limit_choices_to=reduce(
operator.xor,
map(query_group_lkup, getattr(settings, 'AUTHORIZED_AUTHORS', ''))
)
Tested in Django 1.6.1
on Python 2.7.5
11👍
Django 4.1 added support for XOR:
Q
objects and querysets can now be combined using^
as the exclusive or (XOR
) operator.XOR
is natively supported on MariaDB and MySQL. For databases that do not supportXOR
, the query will be converted to an equivalent usingAND
,OR
, andNOT
.
It means you can now write Foobar.objects.filter(Q(blah=1) ^ Q(bar=2))
without monkey patching.
It was worth waiting nine years, wasn’t it?
Source:stackexchange.com