'Is it possible to modify Django Q() objects after construction?
Is it possible to modify Django Q() objects after construction? I create a Q() object like so:
q = Q(foo=1)
is it possible to later change q
to be the same as if I had constructed:
q2 = Q(foo=1, bar=2)
? There's no mention of such an interface in the Django docs that I could find.
I was looking for something like:
Q.append_clause(bar=2)
Solution 1:[1]
You can just make another Q() object and AND them together:
q2 = q & Q(bar=2)
Solution 2:[2]
You can add Q objects together, using their add
method. For example:
>>> q = Q(sender=x)
>>> q.add(Q(receiver=y), Q.AND)
The second argument to add
is the connector, which can also be Q.OR
EDIT: My answer is merely a different way of doing what Perrin Harkins suggested, but regarding your other concern, about different behavior of filter
depending on the way you construct the query, you don't have to worry about that if you join Q objects. My example is equivalent to filter(sender=x, receiver=y)
, and not filter(sender=x).filter(receiver=y)
, because Q objects, as far as I could see in a quick test, do an immediate AND on the clauses and don't have the special behavior of filter
for multi-valued relations.
In any case, nothing like looking at the SQL and making sure it really is doing the same in your specific queries.
Solution 3:[3]
The answers here are a little old and unsatisfactory imo. So here is my answer
This is how you deep copy:
def deep_copy(q: Q) -> Q:
new_q = Q()
# Go through the children of a query: if it's another
# query it will run this function recursively
for sub_q in q.children:
# Make sure you copy the connector in
# case of complicated queries
new_q.connector = q.connector
if isinstance(sub_q, Q):
# This will run recursively on sub queries
sub_q = get_employee_q(sub_q)
else:
pass # Do your modification here
new_q.children.append(sub_q)
return new_q
In the else condition is where your stuff (name='nathan'
for example) is defined. You can change or delete that if you'd like and the Query should work fine.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Perrin Harkins |
Solution 2 | |
Solution 3 | Ysrninja |