Wie verwende ich die Paginierung mit generischen ListViews auf Django-Klassen?

182

Wie verwende ich die Paginierung mit Django 1.3?

Die Dokumentation ist dazu nicht sehr klar.

  • Was geht zu meinem views.py?

  • Was geht zu meiner Vorlage?

  • Was geht zu meiner URLconf-Datei?

gath
quelle

Antworten:

338

Ich denke, Sie fragen nach Informationen zur Verwendung der Paginierung mit den neuen klassenbasierten Ansichten, da diese mit herkömmlichen funktionsbasierten Ansichten leicht zu finden sind. Ich fand, dass nur durch Setzen der paginate_byVariablen ausreicht, um die Paginierung zu aktivieren. Siehe in Klassenbasierte generische Ansichten .

Zum Beispiel in Ihrem 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 !!

In Ihrer Vorlage ( car_list.html) können Sie eine Paginierung Abschnitt wie folgt enthalten (wir einige Kontextvariablen zur Verfügung haben: is_paginated, page_obj, und 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.** .... #}

Die anzuzeigende Seite wird durch einen GET-Parameter angezeigt ?page=n, der der URL einfach hinzugefügt wird.

Ervin
quelle
1
Das ist in Ordnung, aber wie bindet man die Vorlage auch, um das Objekt "car_list" zu sehen?
Gath
28
Zu Ihrer Information können Sie dies auch direkt in urls.py:url(r'^cars/$ ', ListView.as_view (model = Car, paginate_by = 10)),
shawnwall
Lektion, die ich gelernt habe: Um eine Methode zu finden, öffnen Sie alle Ahnenklassen in neuen Registerkarten und drücken Sie STRG + F, um das Schlüsselwort zu entfernen. Öffnen Sie daher unter docs.djangoproject.com/de/dev/ref/class-based-views/… , von dem wir wissen, dass es aus dem grundlegenden Tutorial stammt, alle Ancestors-Links und suchen Sie nach "pagi"
Ciro Santilli 郝海东 冠状 病 六四 事件26
2
Ich habe dies getan, aber das Problem, das ich finde, ist, wenn ich Objekte im Abfragesatz zusätzlich verarbeite, werden sie auf alle Ergebnisse in der Datenbank angewendet. Bei einer Abfrage, die 100 Objekte zurückgibt, aber nur zehn Objekte pro Seite anzeigt, wird die zusätzliche Verarbeitung für 100 Objekte durchgeführt.
Wobbily_col
32
Ich weiß nicht , wie die fest einprogrammierten Urls können Sie es mit ersetzen: <a href="?page={{ page_obj.previous_page_number }}"> vorherigem </a>
dalore
42

Angenommen, ich habe eine Klasse in app / models.py mit dem Namen 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

nur eine kleine Änderung im get_context_dataund hinzugefügten Paginierungscode aus der Django-Dokumentation hier

app / templates / app / exam_list.html

normale Inhaltsliste

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

paginieren Abschnitt

{% 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'),
), 
... ]
Yanwar Sky
quelle
1
Das sieht nicht richtig aus : context = super(SoalListView, self).... Meinten Sie : context = super(FileExamListView, self)...?
Cezar
1

Wir haben 2 Methoden, um dies zu tun.

Das erste ist einfach und setzt einfach das Klassenfeld paginate_by. Mit der get_context_dataMethode brauchen wir nichts zu tun .

Die zweite Methode ist etwas kompliziert, aber wir können die Paginierung besser verstehen und die komplexe Paginierung oder mehrere Paginierungen anpassen. Mal sehen.

Dies kann in drei Schritten erfolgen.

1. Überschreiben Sie die get_context_dataMethode Ihres View.

Bestehen page_keysund pagesdamit wir die Listen iterieren und Hardcodierung vermeiden können.

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. Passen Sie Ihr Sub an template.

Wir definieren einige Variablen, damit wir die Paginierungsliste durchlaufen können.

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. Außen anpassen 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 %}
W.Perrin
quelle