django-filter使用分页

Anh*_*yen 14 python django pagination django-filter

我正在使用该django-filter包在我的列表视图上提供搜索功能.

现在我想为该视图添加一个分页.
我正在尝试将分页与过滤的查询集结合起来,但我不知道如何继续.

到目前为止,我已经尝试了以下内容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})
Run Code Online (Sandbox Code Playgroud)

Eli*_*adi 10

为了添加答案,我也使用 html 表以及 django-filters 和 Paginator 来完成。以下是我的视图和模板文件。需要模板标签来确保将正确的参数传递给分页 URL。

搜索视图.py

from django.shortcuts import render
from app.models.filters_model import ApiStatusFilter
from app.models.api_status import ApiStatus
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from datetime import datetime, timedelta

def status(request):
    all_entries_ordered = ApiStatus.objects.values().order_by('-created_at')[:200]

    for dictionarys in all_entries_ordered:
        dictionarys

    apistatus_list = ApiStatus.objects.values().order_by('-created_at')
    apistatus_filter = ApiStatusFilter(request.GET, queryset=apistatus_list)

    paginator = Paginator(apistatus_filter.qs, 10)
    page = request.GET.get('page')
    try:
        dataqs = paginator.page(page)
    except PageNotAnInteger:
        dataqs = paginator.page(1)
    except EmptyPage:
        dataqs = paginator.page(paginator.num_pages)

    return render(request, 'status_page_template.html', {'dictionarys': dictionarys, 'apistatus_filter': apistatus_filter, 'dataqs': dataqs, 'allobjects': apistatus_list})
Run Code Online (Sandbox Code Playgroud)

状态模板.html

{% load static %}
{% load my_templatetags %}

<!DOCTYPE html>
<html lang="en">
    <head>
        <link rel="stylesheet" type="text/css" href="{% static 'css/table_styling.css' %}">
        <meta charset="UTF-8">
        <title>TEST</title>
    </head>

    <body>
         <table>
            <thead>
                <tr>
                    {% for keys in dictionarys.keys %} 
                        <th>{{ keys }}</th>
                    {% endfor %}
                </tr>
            </thead>
                <form method="get">
                    {{ apistatus_filter.form.as_p }}
                    <button type="submit">Search</button>
                        {% for user in dataqs.object_list %}
                        <tr>
                            <td>{{ user.id }}</td>
                            <td>{{ user.date_time }}</td>
                            <td>{{ user.log }}</td>
                        </tr>
                        {% endfor %}
                </form>
            </tbody>
        </table>

        <div class="pagination">
            <span>
                {% if dataqs.has_previous %}
                    <a href="?{% query_transform request page=1 %}">&laquo; first</a>
                    <a href="?{% query_transform request page=dataqs.previous_page_number %}">previous</a>
                {% endif %}

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

                {% if dataqs.has_next %}
                    <a href="?{% query_transform request page=dataqs.next_page_number %}">next</a>
                    <a href="?{% query_transform request page=dataqs.paginator.num_pages %}">last &raquo;</a>
                {% endif %}
            </span>
        </div> 
    </body>
</html>
Run Code Online (Sandbox Code Playgroud)

my_templatetags.py

from django import template

register = template.Library()

@register.simple_tag
def query_transform(request, **kwargs):
    updated = request.GET.copy()
    for k, v in kwargs.items():
        if v is not None:
            updated[k] = v
        else:
            updated.pop(k, 0)

    return updated.urlencode()
Run Code Online (Sandbox Code Playgroud)


小智 7

我花了一些时间才找到更干燥和更清洁的解决方案来解决此问题,在我看来,最好的解决方案是使用模板标签的解决方案。

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
Run Code Online (Sandbox Code Playgroud)

并在你的模板中

<a href="{% relative_url i 'page' request.GET.urlencode %}">{{ i }}</a>
Run Code Online (Sandbox Code Playgroud)

来源:处理查询字符串参数


Joh*_*fis 6

要使用Django过滤器并对过滤后的结果进行分页,您可以执行以下操作:

  1. 为模型创建一个过滤器类:

    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', ...]
    
    Run Code Online (Sandbox Code Playgroud)
  2. 每个FilterSet对象都有一个.qs包含过滤查询集的属性,如果需要,您甚至可以覆盖它

  3. 我们将对我们的.qs财产进行分页MyModelFilter

    my_project/my_app/views.py

    from . import filters
    from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
    
    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}
        )
    
    Run Code Online (Sandbox Code Playgroud)

在那里,您拥有了!


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)
Run Code Online (Sandbox Code Playgroud)


小智 6

这对我有用:

在我的模板中而不是使用它

<li><a href="?page={{ i }}">{{ i }}</a></li>
Run Code Online (Sandbox Code Playgroud)

我写了这个:

{% 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 %}
Run Code Online (Sandbox Code Playgroud)

我希望它有帮助:)

  • 唯一的问题是,就像@DonExo 在他的回答中所说的,页面参数被附加到 url。但它的工作虽然。 (3认同)