Always True Q Object

I want to create a part of the Django ORM filter dynamically, now I can do:

if some: Obj.filter( some_f1=some_v1, f1=v1, f2=v2, f3=v3, f4=v4, ... ) else: Obj.filter( f1=v1, f2=v2, f3=v3, f4=v4, ... ) 

I want something without duplicating the code as follows:

 Obj.filter( Q(some_f1=some_v1) if some else True, # what to use instead of True? f1=v1, f2=v2, f3=v3, f4=v4, ... ) 
+7
django django-orm django-q
source share
5 answers

Here's a hacker way to always get a true Q object:

 always_true = ~Q(pk=None) 

It depends on the fact that the primary key cannot be null.

+6
source share

Try it;

 conditions = {'f1':f1,'f2':f2, 'f3':f3} if some: conditions['some_f1'] = some_v1 Obj.objects.filter(**conditions) 
+3
source share

as Alasdair replied in a comment:

 Obj.filter( Q(some_f1=some_v1) if some else Q(), f1=v1, f2=v2, f3=v3, f4=v4, ... ) 
+1
source share

Based on this answer, we can make a conditional argument passing

 Obj.filter( *( (Q(some_f1=some_v1),) if some else ()), f1=v1, f2=v2, f3=v3, f4=v4, ... ) 

So, if some is True , add tuple (Q(some_f1=some_v1),) to the argument list, otherwise add an empty set () , we also need to wrap it in *() , as always, when we go through a tuple without key words args

0
source share

Since QuerySets are lazy , you can create a default filter and then add other databases to your conditions. Django will not run the query until the QuerySet has been evaluated (e.g. iterating through it in a for loop)

 filtered_objects = Obj.filter( some_f1=some_v1, f1=v1, f2=v2, f3=v3, f4=v4, ... ) if some: filtered_objects.filter(some_f1=some_v1) 
0
source share

All Articles