Làm cách nào để sử dụng phân trang với ListViews chung dựa trên lớp Django?


182

Làm cách nào để sử dụng phân trang với Django 1.3?

Các tài liệu không rõ ràng về điều này.

  • Những gì đi đến của tôi views.py?

  • Điều gì đi đến mẫu của tôi?

  • Điều gì đi đến tập tin URLconf của tôi?

Câu trả lời:


338

Tôi nghĩ rằng bạn hỏi thông tin về việc sử dụng phân trang với các khung nhìn dựa trên lớp mới vì, với các khung nhìn dựa trên chức năng truyền thống, rất dễ tìm thấy. Tôi thấy rằng chỉ bằng cách đặt paginate_bybiến là đủ để kích hoạt phân trang. Xem trong các khung nhìn chung dựa trên lớp .

Ví dụ: trong 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 !!

Trong mẫu của bạn ( car_list.html), bạn có thể bao gồm một phần pagination như thế này (chúng tôi có một số biến bối cảnh có sẵn: is_paginated, page_obj, và 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.** .... #}

Trang để hiển thị được biểu thị bằng tham số GET, chỉ cần thêm ?page=nvào URL.


1
Đó là ok, nhưng làm thế nào để bạn buộc mẫu quá nhìn thấy đối tượng "car_list"?
gath

28
FYI bạn cũng có thể thực hiện việc này trực tiếp trong urls.py:url(r'uccicars/$ ', ListView.as_view (model = Car, paginate_by = 10)),
shawnwall

bài học tôi đã học: để tìm một phương thức, mở tất cả các lớp tổ tiên trong các tab mới và CTRL + F đi từ khóa. vì vậy, từ docs.djangoproject.com/en/dev/ref/ class-basing -views / , mà chúng ta biết tồn tại từ hướng dẫn cơ bản, mở tất cả các liên kết Tổ tiên và tìm kiếm "pagi"
Ciro Santilli 郝海东 冠状 病 六四 事件法轮功

2
Tôi đã làm điều này, nhưng vấn đề tôi tìm thấy, là khi tôi xử lý thêm vào các đối tượng trong bộ truy vấn, nó áp dụng chúng cho tất cả các kết quả trong cơ sở dữ liệu. Vì vậy, đối với truy vấn trả về 100 đối tượng, nhưng chỉ hiển thị mười đối tượng trên mỗi trang, việc xử lý bổ sung sẽ được thực hiện trên 100 đối tượng.
wobbily_col

32
Tôi không giống như các url hardcoded bạn có thể thay thế nó bằng: <a href="?page={{ page_obj.previous_page_number }}"> trước </a>
dalore

42

giả sử, tôi có một lớp trong app / model.py có tên FileExam(models.Model):

ứng dụng / mô hình

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)

ứng dụng / lượt xem

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

chỉ có một chút thay đổi trong get_context_datavà thêm mã phân trang từ tài liệu django ở đây

ứng dụng / mẫu / ứng dụng / tests_list.html

danh sách nội dung bình thường

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

phần phân trang

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

ứng dụng / url

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

1
Điều này có vẻ không đúng : context = super(SoalListView, self).... Ý bạn là context = super(FileExamListView, self)...sao?
cezar

1

Chúng tôi có 2 phương pháp để làm điều này.

Đầu tiên là đơn giản và chỉ cần thiết lập trường lớp paginate_by. Không có gì chúng ta cần phải làm với get_context_dataphương pháp.

Phương pháp thứ hai hơi phức tạp nhưng chúng ta có thể hiểu rõ hơn về phân trang và tùy chỉnh phân trang phức tạp hoặc một số phân trang. Chúng ta hãy xem nó.

Nó có thể được thực hiện trong ba bước.

get_context_dataPhương pháp 1.Override của bạn View.

Vượt qua page_keyspagesđể chúng ta có thể lặp lại các danh sách và tránh mã hóa cứng.

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. Tùy chỉnh phụ của bạn template.

Chúng tôi xác định một số biến để chúng tôi có thể lặp qua danh sách phân trang.

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. Tùy chỉnh bên ngoài 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 %}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.