Conditional nested filters in Django
I have a django model, lets say:
class Person(models.Model):
first_name = models.CharField(max_length=25)
last_name = models.CharField(max_length=25)
And, exists a search form, where I can search rows whether by first_name, by last_name or by both. I have noted that I can link filters in a django queryset, e.g:
def search(request):
list = Person.objects.filter(first_name= val1).filter(last_name=val2)
But what if one of the values val1, val2 is null? Should I do something like:
def searh(request):
if val1 != null and val2 == null:
list = Person.objects.filter(first_name= val1)
if val2 == null and val2 != null:
list = Person.objects.filter(last_name= val2)
if val2 != null and val2 != null:
list = Person.objects.filter(first_name= val1).filter(last开发者_Go百科_name=val2)
Is there any direct way to do this?
thanks in advance
def search(request, val1, val2):
persons = Person.objects.all()
if val1:
persons = persons.filter(first_name=val1)
if val2:
persons = persons.filter(last_name=val2)
return persons
This works (isn't inefficient) because Querysets are lazy.
(Disclaimer: tested in Python 2.7, Django 1.6, although it should work in general)
I've been recently introduced to the following construct that directly applies to OP's issue:
def search(request, val1, val2):
filter_args={}
if val1:
filter_args["first_name"]=val1
if val2:
filter_args["last_name"]=val2
persons = Person.objects.filter(**filter_args)
return persons
Basically, this will construct a filter with more than one criterion, even if you don't know a-priori whether both val1
and val2
will be available. It'll construct the most specific filter using conjunction (and
) it can, without needing extra logic evaluation to overcome the fact that .filter(...).filter(...)
always evaluates the criterions using disjunction (or
). If later you want to add age
to your conjunction, for instance, just add the following two lines (and val3
to the function argument list):
if val3:
filter_args["age"]=val3
I'm using this methodology in a project I'm working on to great success, and thought this information might be useful to newer Django users with this same question.
精彩评论