Django-filter uses pagination

I use the package django-filterto provide a search function in my list view.

Now I want to add pagination to this view.
I am trying to combine pagination into a filtered query, but I do not know how to do this.

So far I have tried the following on views.py:

def search(request):
    qs = local_url.objects.filter(global_url__id=1).all()
    paginator = Paginator(qs, 25)
    page = request.GET.get('page')
    try:
        pub = paginator.page(page)
    except PageNotAnInteger:
        pub = paginator.page(1)
    except EmptyPage:
       pub = paginator.page(paginator.num_pages)
    url_filter = PublicationFilter(request.GET, queryset=qs)
    return render(request, 'ingester/search_list.html', {'filter': url_filter, 'publication':pub})
+9
source share
4 answers

This worked for me:

in my template, instead of using this

<li><a href="?page={{ i }}">{{ i }}</a></li>

I wrote this:

{% if 'whatever_parameter_you_use_to_filter' in request.get_full_path %}
   <li><a href="{{ request.get_full_path }}&page={{ i }}"{{ i }}</a></li>
{% else %}
   <li><a href="?page={{ i }}">{{ i }}</a></li>
{% endif %}

I hope this helps :)

+5
source

Django :

  • :

    my_project/my_app/filters.py:

    import django_filters
    
    class MyModelFilter(django_filters.FilterSet):
        class Meta:
            model = MyModel
            # Declare all your model fields by which you will filter
            # your queryset here:
            fields = ['field_1', 'field_2', ...]
    
  • FilterSet .qs, , .

  • .qs MyModelFilter:

    my_project/my_app/views.py:

    from . import filters
    
    
    def my_view(request):
        # BTW you do not need .all() after a .filter() 
        # local_url.objects.filter(global_url__id=1) will do
        filtered_qs = filters.MyModelFilter(
                          request.GET, 
                          queryset=MyModel.objects.all()
                      ).qs
        paginator = Paginator(filtered_qs, YOUR_PAGE_SIZE)
    
        page = request.GET.get('page')
        try:
            response = paginator.page(page)
        except PageNotAnInteger:
            response = paginator.page(1)
        except EmptyPage:
            response = paginator.page(paginator.num_pages)
    
        return render(
            request, 
            'your_template.html', 
            {'response': response}
        )
    

!


PS_1: Django " " Django Rest Framework.

PS_2: DRF, , , , FilterSet:

@api_view(['GET',])
def my_function_based_list_view(request):
    paginator = PageNumberPagination()
    filtered_set = filters.MyModelFilter(
                       request.GET, 
                       queryset=MyModel.objects.all()
                   ).qs
    context = paginator.paginate_queryset(filtered_set, request)
    serializer = MyModelSerializer(context, many=True)
    return paginator.get_paginated_response(serializer.data)
+2

, , . , "qs" PublicationFilter Paginator:

def search(request):
    qs = local_url.objects.filter(global_url__id=1).all()
    url_filter = PublicationFilter(request.GET, queryset=qs)
    paginator = Paginator(url_filter.qs, 25)
    page = request.GET.get('page')
    try:
        pub = paginator.page(page)
    except PageNotAnInteger:
        pub = paginator.page(1)
    except EmptyPage:
        pub = paginator.page(paginator.num_pages)
    url_filter = PublicationFilter(request.GET, queryset=qs)
    return render(request, 'ingester/search_list.html', {'publication':pub})

url_filter.qs QuerySet
url_filter.queryset QuerySet

+1

- , URL .

{% if pages.has_previous %}
<li><a href="?page={{ pages.previous_page_number }}">Prev</a></li>
{% endif %}

, .

, django-fitler, django-fitler ( '?') -, ?page=2 .

, , "" "" - django-fitler &page=5 .

@stathoula, , . , -, &page=3.

This seems very simple, but I had to make a small hacker so as not to repeat &page=1again and again inside the query line when the user clicks through the arrows.

In my case, title is used as a filter, so I need to check if it is present there.

Here is a snippet of what I did, works great for my project.

templates / pagination.html

<div class="paginator">

    {% with request.get_full_path as querystring %}
        <ul class="pagination nav navbar-nav">

            <!-- Previous page section -->
            {% if pages.has_previous %}
                {% if 'title' in querystring %}
                    {% if 'page' in querystring %}
                        <li class="paginator {% if pages.number == page %}active{% endif %}">
                            <a href="{{ querystring|slice:":-7" }}&page={{ pages.previous_page_number }}">Prev</a>
                        </li>
                    {% else %}
                        <li class="paginator {% if pages.number == page %}active{% endif %}">
                            <a href="{{ querystring }}&page={{ pages.previous_page_number }}">Prev</a>
                        </li>
                    {% endif %}
                {% else %}
                    <li class="paginator {% if pages.number == page %}active{% endif %}">
                        <a href="?page={{ pages.previous_page_number }}">Prev</a>
                    </li>
                {% endif %}
            {% endif %}

            <!-- All pages section -->
            {% for page in pages.paginator.page_range %}
                {% if 'title' in querystring %}
                    {% if 'page' in querystring %}
                        <li class="paginator {% if pages.number == page %}active{% endif %}">
                            <a href="{{ querystring|slice:":-7" }}&page={{ page }}">{{ page }}</a>
                        </li>
                    {% else %}
                        <li class="paginator {% if pages.number == page %}active{% endif %}">
                            <a href="{{ querystring }}&page={{ page }}">{{ page }}</a>
                        </li>
                    {% endif %}
                {% else %}
                    <li class="paginator {% if pages.number == page %}active{% endif %}">
                        <a href="?page={{ page }}">{{ page }}</a>
                    </li>
                {% endif %}
            {% endfor %}

            <!-- Next page section -->
            {% if pages.has_next %}
                {% if 'title' in querystring %}
                    {% if 'page' in querystring %}
                        <li class="paginator {% if pages.number == page %}active{% endif %}">
                            <a href="{{ querystring|slice:":-7" }}&page={{ pages.next_page_number }}">Next</a>
                        </li>
                    {% else %}
                        <li class="paginator {% if pages.number == page %}active{% endif %}">
                            <a href="{{ querystring }}&page={{ pages.next_page_number }}">Next</a>
                        </li>
                    {% endif %}
                {% else %}
                    <li class="paginator {% if pages.number == page %}active{% endif %}">
                        <a href="?page={{ pages.next_page_number }}">Next</a>
                    </li>
                {% endif %}
            {% endif %}

        </ul>
    {% endwith %}

</div>

Here is a view, just in case:

App /views.py

def index(request):
    condo_list = Condo.objects.all().order_by('-timestamp_created')
    condo_filter = CondoFilter(request.GET, queryset=condo_list)

    paginator = Paginator(condo_filter.qs, MAX_CONDOS_PER_PAGE)
    page = request.GET.get('page')

    try:
        condos = paginator.page(page)
    except PageNotAnInteger:
        condos = paginator.page(1)
    except EmptyPage:
        condos = paginator.page(paginator.num_pages)


    return render(request, 'app/index.html', {
        'title': 'Home',
        'condos': condos,
        'page': page,
        'condo_filter': condo_filter,
    })

Here is a working example:

.

+1
source

All Articles