首页 文章

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

提问于
浏览
165

如何使用Django 1.3分页?

文档对此不太清楚 .

  • 我的 views.py 会怎样?

  • 我的模板有什么用途?

  • 我的URLconf文件是什么?

3 回答

  • 312

    假设,我在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
    

    get_context_data 只有一点变化,并添加了来自django文档的分页代码here

    app/templates/app/exam_list.html

    normal content list

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

    paginate section

    {% 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'),
    ), 
    ... ]
    
  • 37

    我想你要求提供有关使用新的基于类的视图分页的信息,因为使用传统的基于函数的视图,它很容易找到 . 我发现只需设置 paginate_by 变量即可激活分页 . 见Class-based generic views .

    例如,在 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_objpaginator ) .

    {# .... **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=n 添加到URL即可 .

  • 0

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

    第一个很简单,只需设置类字段 paginate_by . 我们不需要使用 get_context_data 方法 .

    第二种方法有点复杂但我们可以更好地理解分页并定制复杂的分页或几个分页 . 让我们来看看它 .

    它可以分三步完成 .

    1.覆盖View的get_context_data方法 .

    传递 page_keyspages ,以便我们可以迭代列表并避免硬编码 .

    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.自定义子模板 .

    我们定义了一些变量,因此我们可以遍历分页列表 .

    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.自定义外部模板 .

    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 %}
    

相关问题