rahnama7m
rahnama7m

Reputation: 977

Check is_null for list of field in Django queryset filtering

I have create model with this fields:

field_1 , field_2, field_3, ... , field_n

And I want to filter all objects that these k fields:

field_1 , field_2, .... , field_k

of those objects is n't Null.

My wrong answer:

I did think that I must create this list of fields that I want to set in my query:

my_list = [`field_1` , `field_2`, .... , `field_k`]

and create my query like this:

my_objects = Class.objects.filter([ (eval(field_name +"__isnull = False") )  for field_name in my_list ])

But it was wrong. How can I do that?

Upvotes: 2

Views: 563

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476624

You make things too complicated, you can not construct a list with strings and pass it to filter(..) in the hope that it will work. Furthermore eval(..) does not work that way, and even if it did, it would result in severe security risks. eval(..) and exec(..) should be avoided as much as possible, since from the moment someone manages to "inject" a string into it, they can run arbitrary code on your server, and thus try to "dump the database", etc. See this answer for a more in-depth analysis on why "Eval is bad practice".

You can construct a list of fields names (so strings):

my_list = ['field_1', 'field_2', 'field_k']

Then we can construct a dictionary and perform dictionary unpacking, like:

Class.objects.filter(**{'{}__isnull'.format(f): False for f in my_list})

The two asterisks (**), will thus make a function call, such that f(**{'a': 4, 'b': 2}), is the same as f(a=4, b=2), and thus here it will make a call like .filter(field_1__isnull=False, field_2__isnull=False, field_k__isnull=False).

Or since , we can make use of f-strings:

Class.objects.filter(**{f'{f}__isnull': False for f in my_list})

Upvotes: 2

Related Questions