Queryset in Django if empty field returns all elements

846 views Asked by At

I want to do a filter in Django that uses form method. If the user type de var it should query in the dataset that var, if it is left in blank to should bring all the elements.

How can I do that?

I am new in Django

if request.GET.get('Var'):
    Var = request.GET.get('Var')
else:
    Var = WHAT SHOULD I PUT HERE TO FILTER ALL THE ELEMNTS IN THE CODE BELLOW

models.objects.filter(Var=Var)
2

There are 2 answers

6
Robert Townley On BEST ANSWER

It's not a great idea from a security standpoint to allow users to input data directly into search terms (and should DEFINITELY not be done for raw SQL queries if you're using any of those.)

With that note in mind, you can take advantage of more dynamic filter creation using a dictionary syntax, or revise the queryset as it goes along:

Option 1: Dictionary Syntax

def my_view(request):
  query = {}
  if request.GET.get('Var'):
     query['Var'] = request.GET.get('Var')
  if request.GET.get('OtherVar'):
    query['OtherVar'] = request.GET.get('OtherVar')
  if request.GET.get('thirdVar'):
    # Say you wanted to add in some further processing
    thirdVar = request.GET.get('thirdVar')
    if int(thirdVar) > 10:
       query['thirdVar'] = 10
    else:
       query['thirdVar'] = int(thirdVar)
  if request.GET.get('lessthan'):
    lessthan = request.GET.get('lessthan')
    query['fieldname__lte'] = int(lessthan)
  results = MyModel.objects.filter(**query)

If nothing has been added to the query dictionary and it's empty, that'll be the equivalent of doing MyModel.objects.all()

My security note from above applies if you wanted to try to do something like this (which would be a bad idea):

MyModel.objects.filter(**request.GET)

Django has a good security track record, but this is less safe than anticipating the types of queries that your users will have. This could also be a huge issue if your schema is known to a malicious site user who could adapt their query syntax to make a heavy query along non-indexed fields.

Option 2: Revising the Queryset Alternatively, you can start off with a queryset for everything and then filter accordingly

def my_view(request):
  results = MyModel.objects.all()
  if request.GET.get('Var'):
     results = results.filter(Var=request.GET.get('Var'))
  if request.GET.get('OtherVar'):
    results = results.filter(OtherVar=request.GET.get('OtherVar'))
  return results
0
kichik On

A simpler and more explicit way of doing this would be:

if request.GET.get('Var'):
    data = models.objects.filter(Var=request.GET.get('Var'))
else:
    data = models.objects.all()