Как создать несколько фильтров в Django?

Я хочу создать несколько фильтров в Django.

Приведенный ниже снимок экрана объясняет это.

enter image description here

Пользователь может не выбирать некоторые критерии.

Если пользователь не выбирает 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

enter image description here

Ссылка на репозиторий GitHub

Я написал код, но я думаю, что должен быть лучший способ.

Простым решением вашей проблемы является создание сложных запросов с помощью 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)
Вернуться на верх