I have several Django forms of which when submitted I store the values like so if the forms are valid with only the min and max price being required, but the other values may be blank or not:
max_budget = price_form.cleaned_data['max_price'] #required
max_budget = price_form.cleaned_data['max_price'] #required
another_value1 = other_form1.cleaned_data['another_value1'] #string
another_value2 = other_form1.cleaned_data['another_value2'] #string
another_value3 = other_form2.cleaned_data['another_value3'] #string
another_value4 = other_form2.cleaned_data['another_value4'] #string
another_value5 = other_form3.cleaned_data['another_value5'] #boolean value
another_value6 = other_form3.cleaned_data['another_value6'] #boolean value
I want to query a model (single database table) by using these variable values which correspond to specific fields in that DB as filters. The problem is that currently, I would have to use numerous carefully planned nested if/else statements each containing a variation of the line below to properly filter the DB based on the different possible values or lack thereof.
query_results = Model.objects.filter(price__range=(min_budget, max_budget), field_in_the_DB="another_value1", field_in_the_DB="another_value2", field_in_the_DB__icontains="another_value3", field_in_the_DB__icontains="another_value4", field_in_the_DB="another_value5", field_in_the_DB="another_value6").order_by("Another_field_in_the_DB_not_related_these_values")
This is because only the min and max prices are required to be entered so something like this would be required.
price__range=(min_budget, max_budget)
As for the other variables, some may have values or some may be left blank when submitted. Therefore, how can I filter the DB table efficiently without having to use numerous if/else statements to account for the different possible values or lack thereof? Is there a simpler way?
CodePudding user response:
I use a Q filter. You are not saved from the "IF" but you can have them ordered.
from django.db.models import Q
# this condition must always exist otherwise the filter fails
my_filter = Q( price__range=(min_budget, max_budget) )
#I use Get, modify for POST if necessary
if self.request.GET.get("other_value1", ""):
my_filter &= Q( field_in_the_DB="other_value1" )
if self.request.GET.get("other_value2", ""):
my_filter &= Q( field_in_the_DB="other_value2" )
if self.request.GET.get("other_value3", ""):
my_filter &= Q(field_in_the_DB__icontains="another_value3" )
if self.request.GET.get("other_value4", ""):
my_filter &= Q(field_in_the_DB__icontains="another_value4" )
if self.request.GET.get("other_value5", ""):
my_filter &= Q( field_in_the_DB="other_value5" )
if self.request.GET.get(other_value6):
my_filter &= Q( field_in_the_DB="other_value6" )
query_results = Model.objects.filter(my_filter).order_by("...")
see the &= in assignments I hope it helps you.
CodePudding user response:
You can use a dict, and pass it as **kwargs in the filter.
Example
query_params = {
'field_in_db': value,
'another_field__icontains': another_value
}
query_results = Model.objects.filter(**query_params) # the rest of the queryset
CodePudding user response:
I would first like to say thank you very much to Daniel Acuña as your answer is for the most part correct and you deserve 99.9% of the credit for providing it.
However, I did make changes to the if statement as I realized that they were being skipped over and not being accessed.
Here are the minor changes I made to the if statements:
if other_value1:
my_filter &= Q( field_in_the_DB="other_value1" )
if other_value2:
my_filter &= Q( field_in_the_DB="other_value2" )
if other_value3:
my_filter &= Q(field_in_the_DB__icontains="another_value3" )
if other_value4:
my_filter &= Q(field_in_the_DB__icontains="another_value4" )
if other_value5:
my_filter &= Q( field_in_the_DB="other_value5" )
if other_value6:
my_filter &= Q( field_in_the_DB="other_value6" )