web-dev-qa-db-fra.com

Comment utiliser la pagination avec ListViews générique basé sur la classe Django?

Comment utiliser la pagination avec Django 1.3? 

La documentation n'est pas très claire à ce sujet.

  • Qu'est-ce qui se passe dans mon views.py?

  • Qu'est-ce qui se passe dans mon modèle?

  • Qu'est-ce qui va dans mon fichier URLconf?

166
gath

Je pense que vous demandez des informations sur l'utilisation de la pagination avec les nouvelles vues basées sur les classes car, avec les vues traditionnelles basées sur les fonctions, il est facile à trouver. J'ai trouvé que le simple fait de définir la variable paginate_by suffit à activer la pagination. Voir dans Vues génériques basées sur les classes.

Par exemple, dans votre 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 !!

Dans votre modèle (car_list.html), vous pouvez inclure une section de pagination comme celle-ci (certaines variables de contexte sont disponibles: is_paginated, page_obj et 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.** .... #}

La page à afficher est indiquée par un paramètre GET, en ajoutant simplement ?page=n à l'URL.

313
ervin

supposons que j'ai une classe dans app/models.py nommée 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

seulement un petit changement dans le get_context_data et le code de pagination ajouté à partir de la documentation Django ici

app/templates/app/exam_list.html

liste de contenu normale

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

paginer la 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
Yanwar Sky

Nous avons 2 méthodes pour le faire.

Le premier est simple et il suffit de définir le champ de classe paginate_by. Nous n'avons rien à faire avec la méthode get_context_data.

La seconde méthode est un peu compliquée, mais nous pouvons mieux comprendre la pagination et personnaliser la pagination complexe ou plusieurs paginations. Voyons ça.

Cela peut être fait en trois étapes.

1. Méthode de substitution get_context_data de votre View.

Passez page_keys et pages afin que nous puissions parcourir les listes et éviter de coder en dur.

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. Personnalisez votre sous template.

Nous définissons certaines variables pour pouvoir parcourir la liste de pagination.

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.Customize outer 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 %}
0
W.Perrin