如何对基于Django类的通用ListView使用分页?


182

如何在Django 1.3中使用分页?

该文档对此不是很清楚。

  • views.py怎么了?

  • 我的模板如何处理?

  • 我的URLconf文件中有什么内容?

Answers:


338

我认为您需要有关将分页与基于新类的视图一起使用的信息,因为基于传统函数的视图很容易找到。我发现仅通过设置paginate_by变量就足以激活分页。请参见基于类的通用视图

例如,在您的views.py

import models
from django.views.generic import ListView

class CarListView(ListView):
    model = models.Car      # shorthand for setting queryset = models.Car.objects.all()
    template_name = 'app/car_list.html'  # optional (the default is app_name/modelNameInLowerCase_list.html; which will look into your templates folder for that path and file)
    context_object_name = "car_list"    #default is object_list as well as model's_verbose_name_list and/or model's_verbose_name_plural_list, if defined in the model's inner Meta class
    paginate_by = 10  #and that's it !!

在你的模板(car_list.html),您可以包括这样的分页部分(我们有一些情境变量可用:is_paginatedpage_obj,和paginator)。

{# .... **Normal content list, maybe a table** .... #}
{% if car_list %}
    <table id="cars">
        {% for car in car_list %}
            <tr>
                <td>{{ car.model }}</td>
                <td>{{ car.year }}</td>
                <td><a href="/car/{{ car.id }}/" class="see_detail">detail</a></td>
            </tr>
        {% endfor %}
    </table>
    {# .... **Now the pagination section** .... #}
    {% if is_paginated %}
        <div class="pagination">
            <span class="page-links">
                {% if page_obj.has_previous %}
                    <a href="/cars?page={{ page_obj.previous_page_number }}">previous</a>
                {% endif %}
                <span class="page-current">
                    Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
                </span>
                {% if page_obj.has_next %}
                    <a href="/cars?page={{ page_obj.next_page_number }}">next</a>
                {% endif %}
            </span>
        </div>
    {% endif %}
{% else %}
    <h3>My Cars</h3>
    <p>No cars found!!! :(</p>
{% endif %}
{# .... **More content, footer, etc.** .... #}

要显示的页面由GET参数指示,只需将?page=nURL 添加到即可。


1
没关系,但是如何将模板也绑定到“ car_list”对象呢?
gath

28
仅供参考,您也可以直接在urls.py:url(r'^cars/$',ListView.as_view(model = Car,paginate_by = 10))中进行此操作
shawnwall

我吸取的教训:找到一种方法,在新选项卡中打开所有祖先类,然后按CTRL + F移开关键字。因此从docs.djangoproject.com/en/dev/ref/class-based-views/…(我们从基本教程中了解到)中打开所有祖先链接并搜索“ pagi”
Ciro Santilli郝海东冠状病六四事件法轮功

2
我一直在这样做,但是我发现的问题是,当我对queryset中的对象进行额外的处理时,它会将它们应用于数据库中的所有结果。因此,对于返回100个对象但每页仅显示10个对象的查询,将对100个对象执行额外的处理。
wobbily_col 2012年

32
我不喜欢将硬编码的网址替换为:<a href="?page={{ page_obj.previous_page_number }}">上一个</a>
dalore

42

假设,我在app / models.py中有一个名为的类FileExam(models.Model)

app / models.py

class FileExam(models.Model):
    myfile = models.FileField(upload_to='documents/%Y/%m/%d')
    date = models.DateTimeField(auto_now_add=True, blank=True)
    teacher_name = models.CharField(max_length=30)
    status = models.BooleanField(blank=True, default=False)

app / views.py

from app.models import FileExam
from django.core.paginator import Paginator
from django.core.paginator import EmptyPage
from django.core.paginator import PageNotAnInteger

class FileExamListView(ListView):
    model = FileExam
    template_name = "app/exam_list.html"
    paginate_by = 10


    def get_context_data(self, **kwargs):
        context = super(SoalListView, self).get_context_data(**kwargs) 
        list_exam = FileExam.objects.all()
        paginator = Paginator(list_exam, self.paginate_by)

        page = self.request.GET.get('page')

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

        context['list_exams'] = file_exams
        return context

只有在AA变化不大get_context_data,并添加分页代码Django文档在这里

app / templates / app / exam_list.html

正常内容清单

<table id="exam">
  {% for exam in list_exams %}
  <tr>
    <td>{{ exam.myfile }}</td>
    <td>{{ exam.date }}</td>
    <td>.....</td>
  </tr>
  {% endfor %}
</table>

分页部分

{% if is_paginated %}
<ul class="pagination">
{% if page_obj.has_previous %}
    <li>
        <span><a href="?page={{ page_obj.previous_page_number }}">Previous</a></span>
    </li>
{% endif %}
    <li class="">
        <span>Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.</span>
    </li>
{% if page_obj.has_next %}
    <li>
        <span><a href="?page={{ page_obj.next_page_number }}">Next</a></span>
    </li>
{% endif %}
</ul>
{% else %}
    <h3>Your File Exam</h3>
    <p>File not yet available</p>
{% endif %}

app / urls.py

urlpatterns = [
url(
    r'^$', views.FileExamListView.as_view(), name='file-exam-view'),
), 
... ]

1
看起来不正确:context = super(SoalListView, self)...。你的意思是:context = super(FileExamListView, self)...
cezar's

1

我们有两种方法可以做到这一点。

第一个很简单,只需设置class字段即可paginate_by。不需要我们使用get_context_data方法。

第二种方法有些复杂,但是我们可以对分页有更多的了解,并可以定制复杂的分页或几种分页。让我们来看看它。

可以通过三个步骤完成。

1.覆盖get_context_data您的方法View

通过page_keys和,pages以便我们可以迭代列表并避免进行硬编码。

def get_context_data(self, *, object_list=None, **kwargs):
    context = super().get_context_data()
    df = pd.DataFrame(list(self.model.objects.all().values()))
    ipc = df.groupby('ip')['ip'].count().sort_values(ascending=False)
    urlc = df.groupby('url')['url'].count().sort_values(ascending=False).to_dict()

    ipc = tuple(ipc.to_dict().items())
    urlc = tuple(urlc.items())

    pages = []
    page_keys = ['page1', 'page2']
    for obj, name in zip([urlc, ipc], page_keys):
        paginator = Paginator(obj, 20)
        page = self.request.GET.get(name)
        page_ipc = obj
        try:
            page_ipc = paginator.page(page)
        except PageNotAnInteger:
            page_ipc = paginator.page(1)
        except EmptyPage:
            page_ipc = paginator.page(paginator.num_pages)
        pages.append(page_ipc)

    context['data'] = zip(pages, page_keys)
    return context

2.自定义您的潜艇template

我们定义一些变量,以便我们可以遍历分页列表。

pagination.html

    {% if is_paginated %}
        <ul class="pagination">
        {% if page_obj.has_previous %}
            <li>
            <span><a href="?{{ pname }}={{ page_obj.previous_page_number }}">Previous</a></span>
            </li>
        {% endif %}
        <li class="">
            <span>Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.</span>
        </li>
        {% if page_obj.has_next %}
            <li>
            <span><a href="?{{ pname }}={{ page_obj.next_page_number }}">Next</a></span>
            </li>
        {% endif %}
        </ul>
    {% else %}
        <h3>Your File Exam</h3>
        <p>File not yet available</p>
    {% endif %}

3.自定义外部template

index.html

{% for foo,name in data %}
    <div class="col-md-3 table-responsive">

            {% for k,v in foo %}
                <tr>
                    <th>{{ forloop.counter }}</th>
                    <td>{{ k }}</td>
                    <td>{{ v }}</td>
                </tr>
            {% endfor %}

        {% include 'pagination.html' with pname=name  page_obj=foo %}
    </div>
{% endfor %}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.