Как создать несколько фильтров в Django?
Я хочу создать несколько фильтров в Django.
Приведенный ниже снимок экрана объясняет это.
Пользователь может не выбирать некоторые критерии.
Если пользователь не выбирает Available from, Available till и Advance, то я получу значение None в файле views.py. Если пользователь не выберет Category или Capacity, то я получу пустой список, иначе я получу список Category или Capacity.
Проблема возникает, когда есть None или пустой список.
Хотя я написал код и он работает нормально, но я хочу знать, есть ли лучший способ сделать это? У моего кода могут возникнуть проблемы, если сложность увеличится.
forms.py
class RoomForm(forms.Form):
ROOM_CATEGORIES = (
('Regular', 'Regular'),
('Executive', 'Executive'),
('Deluxe', 'Deluxe'),
('King', 'King'),
('Queen', 'Queen'),
)
category = forms.MultipleChoiceField(
required=False,
widget=forms.CheckboxSelectMultiple,
choices=ROOM_CATEGORIES,
)
ROOM_CAPACITY = (
(1, '1'),
(2, '2'),
(3, '3'),
(4, '4'),
)
capacity = forms.MultipleChoiceField(
required=False,
widget=forms.CheckboxSelectMultiple,
choices=ROOM_CAPACITY,
)
class TimeInput(forms.TimeInput):
input_type = 'time'
default=datetime.time()
available_from = forms.TimeField(
required=False,
widget=TimeInput(),
)
available_till = forms.TimeField(
required=False,
widget=TimeInput(),
)
advance = forms.IntegerField(
required=False,
)
"""Function to ensure that booking is done for future and check out is after check in"""
def clean(self):
cleaned_data = super().clean()
available_from = cleaned_data.get("available_from")
available_till = cleaned_data.get("available_till")
str_available_from = str(available_from)
str_available_till = str(available_till)
format = '%H:%M:%S'
if str_available_from != 'None':
try:
datetime.datetime.strptime(str_available_from, format).time()
except Exception:
raise ValidationError(
_('Wrong time entered.'),
code='Wrong time entered.',
)
if str_available_till != 'None':
try:
datetime.datetime.strptime(str_available_till, format).time()
except Exception:
raise ValidationError(
_('Wrong time entered.'),
code='Wrong time entered.',
)
if available_till is not None and available_from is not None:
if available_till <= available_from:
raise ValidationError(
"Available till should be after available from.", code='Available till after available from'
)
views.py
if categories == []:
categories = ['Regular', 'Executive', 'Deluxe', 'King', 'Queen']
if capacities == []:
capacities = [1, 2, 3, 4]
if advance is None:
advance = 0
if available_from is None and available_till is None:
room_list = Room.objects.filter(
category__in=categories,
capacity__in=capacities,
advance__gte=advance
)
elif available_from is None:
room_list = Room.objects.filter(
category__in=categories,
available_till__gte=available_till,
capacity__in=capacities,
advance__gte=advance
)
elif available_till is None:
room_list = Room.objects.filter(
category__in=categories,
available_from__lte=available_from,
capacity__in=capacities,
advance__gte=advance
)
else:
room_list = Room.objects.filter(
category__in=categories,
available_from__lte=available_from,
available_till__gte=available_till,
capacity__in=capacities,
advance__gte=advance
)
return room_list
Я написал код, но я думаю, что должен быть лучший способ.
Простым решением вашей проблемы является создание сложных запросов с помощью Q objects
.
Вы можете найти больше информации по этому вопросу здесь.
В противном случае вы можете попробовать несколько фильтров одновременно:
Room.objects.filter(category__in=categories).filter(capacity__in=capacities).filter...
Для одновременного запроса нескольких объектов используйте символ | для их разделения
varName = Room.objects.filter(category__in=categories) | Room.objects.filter(capacity__in=capacities) | Room.objects.filter(capacity__in=capacities)...
Недавно я использовал это в представлении поиска следующим образом
object_list = Post.objects.filter(title__icontains=query) | Post.objects.filter(content__icontains=query) | Post.objects.filter(category__icontains=query) | Post.objects.filter(date_posted__icontains=query) | Post.objects.filter(author__username__icontains=query)