Как написать запрос фильтра Django для нескольких значений, выбранных из формы, без множества операторов if?
У меня есть несколько Django форм, в которых при отправке я сохраняю значения следующим образом: если формы действительны и требуют только минимальную и максимальную цену, но другие значения могут быть пустыми или нет:
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'] #boolen value of 1 if selected
another_value6 = other_form3.cleaned_data['another_value6'] #boolen value of 1 if selected
Я хочу сделать запрос к модели (одной таблице базы данных), используя в качестве фильтров значения переменных, которые соответствуют определенным полям в этой БД. Проблема в том, что в настоящее время мне придется использовать множество тщательно спланированных вложенных операторов if/else, каждый из которых содержит вариацию следующей строки, чтобы правильно отфильтровать БД на основе различных возможных значений или их отсутствия.
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")
Это потому, что требуется ввести только минимальную и максимальную цены, поэтому потребуется что-то вроде этого.
price__range=(min_budget, max_budget)
Что касается других переменных, то некоторые из них могут иметь значения, а некоторые могут оставаться пустыми при отправке. Поэтому, как я могу эффективно фильтровать таблицу DB без необходимости использовать многочисленные операторы if/else для учета различных возможных значений или их отсутствия? Есть ли более простой способ?
Я использую Q-фильтр. Вы не избавлены от "IF", но вы можете заказать их.
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("...")
смотрите &= в заданиях Надеюсь, это поможет вам.
Вы можете использовать дикту, и передать ее как **kwargs в фильтре.
Пример
query_params = {
'field_in_db': value,
'another_field__icontains': another_value
}
query_results = Model.objects.filter(**query_params) # the rest of the queryset
Сначала я хотел бы сказать большое спасибо Даниэлю Акунье, так как ваш ответ по большей части правильный, и вы заслуживаете 99,9% похвалы за его предоставление.
Однако я внес изменения в оператор if, поскольку понял, что они пропускаются и к ним нет доступа.
Вот незначительные изменения, которые я внес в операторы if:
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" )