Есть ли способ использовать разбиение на страницы с django-filter?

Каждый раз, когда я нажимаю ссылку на следующую страницу (которая является запросом на получение), фильтр пропускается, и я получаю соответствующую страницу для всего списка (без фильтра). Например, если я нахожусь на странице 1 для отфильтрованного списка и нажимаю «Далее», я попадаю на страницу 2 для всего нефильтрованного списка. В models.py

class Person(models.Model):
    name = models.CharField(max_length=50, unique=True)
    gender = models.CharField(max_length=7, choices=GENDER_CHOICES)
    category = models.CharField(max_length=20, choices=get_all_category_choices())

В filter.py,

import django_filters

from .models import Person

class PersonFilter(django_filters.FilterSet):

    class Meta:
        model = Person
        fields = [
            'name',
            'gender',
            'category',
        ]

В views.py

def show_all_persons_page(request):
    context = {}

    filtered_person_list = PersonFilter(
        request.GET,
        queryset=Person.objects.all()
    )

    context['filtered_person_list'] = filtered_person_list

    paginated_filtered_person_list = Paginator(filtered_person_list.qs, 3)
    page_number = request.GET.get('page')
    person_page_obj = paginated_filtered_person_list.get_page(page_number)

    context['person_page_obj'] = person_page_obj

    return render(request, 'app1/show_all_persons_page.html', context)

В app1 / show_all_persons_page.html,

<form method="get">
    {{ filtered_person_list.form.as_p }}
    <button type="submit">Search</button>
</form>

{% for person in person_page_obj %}
    <img src="{{ person.picture.url }}" width="240">
    <h2>
        {{person.name}}
        <br>
        {{person.gender}}
        <br>
        {{person.category}}
        <br>
    </h2>
    <br>
{% endfor %}

<div class="pagination">
    <span class="step-links">
        {% if person_page_obj.has_previous %}
            <a href="?page=1">&laquo; first</a>
            <a href="?page={{ person_page_obj.previous_page_number }}">previous</a>
        {% endif %}

        <span class="current">
            Page {{ person_page_obj.number }} of {{ person_page_obj.paginator.num_pages }}.
        </span>

        {% if person_page_obj.has_next %}
            <a href="?page={{ person_page_obj.next_page_number }}">next</a>
            <a href="?page={{ person_page_obj.paginator.num_pages }}">last &raquo;</a>
        {% endif %}
    </span>
</div>

person Kamruzzaman Tauhid    schedule 05.04.2020    source источник
comment
Вам нужно сохранить старую строку запроса (? Name = x & пол = y & category = z), добавив & page = num. Наверное, проще составить список страниц и их URL-адресов в коде просмотра.   -  person Johan Schiff    schedule 05.04.2020
comment
Не могли бы вы подробнее рассказать об этом? Я такого нигде не видел.   -  person Kamruzzaman Tauhid    schedule 06.04.2020
comment
Вот несколько ответов на эту конкретную проблему. stackoverflow.com/ questions / 2047622 /   -  person Johan Schiff    schedule 06.04.2020


Ответы (1)


Решено. Концепция получена из https://simpleisbetterthancomplex.com/snippet/2016/08/22/dealing-with-querystring-parameters.html. Чтобы сохранить текущие параметры URL, мы должны определить настраиваемый тег шаблона. Создайте новый каталог с именем templatetags в app1. Создайте __init__.py внутри этого каталога. Создайте еще один файл .py, скажем, app1_extras. Внутри app1_extras определите настраиваемый тег шаблона следующим образом. app1 / templatetags / app1_extras.py,

from django import template

register = template.Library()

@register.simple_tag
def relative_url(value, field_name, urlencode=None):
    url = '?{}={}'.format(field_name, value)
    if urlencode:
        querystring = urlencode.split('&')
        filtered_querystring = filter(lambda p: p.split('=')[0] != field_name, querystring)
        encoded_querystring = '&'.join(filtered_querystring)
        url = '{}&{}'.format(url, encoded_querystring)
    return url

Это получит наш текущий URL и гарантирует, что параметры указаны вместе с номером страницы. field_name - это строка 'page', а value - номер страницы, которая будет передана из шаблона. urlencode представляет наш текущий URL-адрес в виде строки. В app1 / show_all_persons.html,

{% load app1_extras %}

<form method="get">
    {{ filtered_person_list.form.as_p }}
    <button type="submit">Search</button>
</form>

{% for person in person_page_obj %}
    <img src="{{ person.picture.url }}" width="240">
    <h2>
        {{person.name}}
        <br>
        {{person.gender}}
        <br>
        {{person.category}}
        <br>
    </h2>
    <br>
{% endfor %}

<div class="pagination">
    <span class="step-links">
        {% if person_page_obj.has_previous %}
            <a href="{% relative_url 1 'page' request.GET.urlencode %}">&laquo; first</a>
            <a href="{% relative_url person_page_obj.previous_page_number 'page' request.GET.urlencode %}">previous</a>
        {% endif %}

        <span class="current">
            Page {{ person_page_obj.number }} of {{ person_page_obj.paginator.num_pages }}.
        </span>

        {% if person_page_obj.has_next %}
            <a href="{% relative_url person_page_obj.next_page_number 'page' request.GET.urlencode %}">next</a>
            <a href="{% relative_url person_page_obj.paginator.num_pages 'page' request.GET.urlencode %}">last &raquo;</a>
        {% endif %}
    </span>
</div>

{% load app1_extras%} загрузит наш новый пользовательский тег шаблона. Функция relative_url теперь передается в hrefs для ссылок на наши страницы. Аргументы передаются в том порядке, в котором request.GET.urlencode будет содержать наш текущий URL и будет передан параметру urlencode.

person Kamruzzaman Tauhid    schedule 13.04.2020