Как использовать 3 отдельных фильтра на одной странице?

У меня есть страница, на которой расположены 3 отдельные формы. С помощью формы 1 я могу фильтровать по имени (введенному пользователем) с помощью метода формы Post С помощью формы 2 я могу фильтровать по уровню (из списка) с помощью метода Get С помощью формы 3 я хочу фильтровать по школе (из списка) также с помощью метода Get

В настоящее время форма 1 и 2 работают, выдавая отфильтрованный список чуть ниже на той же странице. Форма 3 тоже работает (правильный выбор виден за URL), но отфильтрованный список остается пустым.

часть файла views.py:

def spells(request):
    if request.method == "POST":
        spellz = request.POST.get('filter-search-name')    
        spells = Underdark_Spells.objects.filter(Q(spell_name__icontains=spellz)).order_by('spell_name')
        return render(request, 'spells.html', {'spells': spells})
    elif request.method == "GET":
        level = request.GET.get('filter-search-level')    
        spells = Underdark_Spells.objects.filter(Q(spell_level=level)).order_by('spell_name')
        return render(request, 'spells.html', {'spells': spells})  
    elif request.method == "GET":
        school = request.GET.get('filter-search-school')    
        spells = Underdark_Spells.objects.filter(Q(spell_school=school)).order_by('spell_name')
        return render(request, 'spells.html', {'spells': spells})       
    else:
        spells = Underdark_Spells.objects.all().order_by('spell_name')
        return render(request, 'spells.html', {'spells': spells}) 

    

def __str__(self):
    return self.name

Я думаю, что проблема заключается в том, как я настроил это с помощью if и elif. Похоже, что таким образом я не могу использовать метод запроса дважды в одном и том же операторе if. Если я закомментирую код формы 2 в файле views.py, то форма 3 будет работать как надо.

Есть ли способ заставить его работать таким образом или мне нужно создать отдельный def для каждого GET?

Вы не можете иметь одинаковые условия в двух разных блоках if/elif.

Вместо этого вы можете сделать это следующим образом:

...
elif request.method == "GET":
    if request.GET.get('filter-search-level'):
        level = request.GET.get('filter-search-level')  
        spells = Underdark_Spells.objects.filter(Q(spell_level=level)).order_by('spell_name')
    elif request.GET.get('filter-search-school'):
        school = request.GET.get('filter-search-school')    
        spells = Underdark_Spells.objects.filter(Q(spell_school=school)).order_by('spell_name')
    return render(request, 'spells.html', {'spells': spells}) 

Вы должны добавить проверку на наличие элемента в строке запроса, так:

def spells(request):
    if request.method == 'POST' and 'filter-search-name' in request.POST:
        spellz = request.POST.get('filter-search-name')    
        spells = Underdark_Spells.objects.filter(Q(spell_name__icontains=spellz))
    elif request.method == 'GET' and 'filter-search-level' in request.POST:
        level = request.GET.get('filter-search-level')    
        spells = Underdark_Spells.objects.filter(Q(spell_level=level))
    elif request.method == 'GET' and 'filter-search-school' in request.POST:
        school = request.GET.get('filter-search-school')    
        spells = Underdark_Spells.objects.filter(Q(spell_school=school))
    else:
        spells = Underdark_Spells.objects.all()
    spells = spells.order_by('spell_name')
    return render(request, 'spells.html', {'spells': spells}) 

При этом код выглядит довольно "уродливо" с большим количеством дублирующегося кода. Также странно использовать GET или POST запрос для поиска данных. Обычно GET-запрос используется для фильтрации данных, а POST-запрос - для обновления сущностей. Используя три разные формы, вы также делаете невозможным простой выбор уровня и школы, например, для применения двух фильтров.

Я бы посоветовал использовать форму, где у вас несколько элементов, и использовать django-filter [GitHub] или по крайней мере Django forms [Django-doc] для удаления шаблонного кода.

Вернуться на верх