• 12 heures
  • Moyenne

Ce cours est visible gratuitement en ligne.

course.header.alt.is_video

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 22/03/2024

Paginez le flux

Paginez le flux principal

Maintenant que nous avons le flux social, ajoutons-y la pagination. La pagination fonctionne en divisant une liste ou QuerySet en plusieurs morceaux de taille égale. On peut ensuite afficher chaque section sur sa propre page.

L’avantage principal de ce procédé ? La performance. Si nous avions des milliers ou même davantage d’instances de  Photo  et   Blog  dans la base de données, et que nous essayions de les charger toutes sur la page en même temps, le temps de chargement serait astronomique. C’est pourquoi il est préférable de paginer. Même les sites qui implémentent un défilement infini chargent et affichent leurs ressources par lots. Découvrez ci-dessous comment paginer la page d'accueil :

Pour paginer une page, utilisez la classe  django.core.paginator.Paginator  .

Vous pouvez fournir n’importe quel itérable (c’est-à-dire une liste ou un QuerySet) à  Paginator  , en plus du nombre d’instances dont vous avez besoin par page. La classe  Paginator  divise alors l’itérable en objets  Page, et chacun d’entre eux contient les résultats pour une page individuelle.

La page sur laquelle vous êtes est alors stockée en tant que chaîne de requête dans l’URL.

C’est quoi, une chaîne de requête ?

Une chaîne de requête est une liste de paires clé-valeur qui est stockée dans l’URL. Elle est caractérisée par son apparition après un?.

Si vous prenez l’URL https://fotoblog.com?page=5, la clé est  page  , et la valeur est  5.

Avec Django, vous pouvez y accéder dans la vue via l’objet  request.GET.

Donc, si vous appelezrequest.GET.get('page'), vous obtiendrez5.

Vous pourrez utiliser ensuite la méthode  Paginator.get_pagepour obtenir un objet représentant la page sur laquelle vous êtes.

Essayons nous-mêmes avec notre flux principal.

from django.core.paginator import Paginator

def home(request):
    blogs = models.Blog.objects.filter(
        Q(author__in=request.user.follows) | Q(starred=True))
    photos = models.Photo.objects.filter(
        uploader__in=request.user.follows).exclude(
            blog__in=blogs
    )
    blogs_and_photos = sorted(
        chain(blogs, photos),
        key=lambda instance: instance.date_created,
        reverse=True
    )
    
    
    paginator = Paginator(blogs_and_photos, 6)
    
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)
    context = {'page_obj': page_obj}
    return render(request, 'blog/home.html', context=context)

Mettez maintenant à jour le gabarit pour utiliser le paginateur. Plutôt que d’itérer dans la liste d’origine, vous itérez désormais danspage_obj.

{% extends 'base.html' %}
{% load blog_extras %}

{% block content %}
    <h2>Votre flux</h2>
    {% for instance in page_obj %}
        {% if instance|model_type == 'Blog' %}
            {% include 'blog/partials/blog_snippet.html' with blog=instance %}
        {% elif instance|model_type == 'Photo' %}
            {% include 'blog/partials/photo_snippet.html' with blog=instance %}
        {% endif %}
    {% endfor %}
{% endblock content %}

Voyons à quoi ça ressemble :

Capture d'écran du flux
Capture d'écran du flux

Le flux est maintenant limité à six billets et photos par page, mais il n’y a aucun moyen de naviguer entre les pages.

Nous devons également ajouter une section à la fin qui donne le numéro de page à l’utilisateur et lui permette de naviguer vers l’avant et vers l’arrière.

La variable  page_obj  a des attributs pratiques que vous pouvez utiliser pour générer ces éléments de navigation.

Voyons de quoi ça ressemble dans le gabarit.

{% extends 'base.html' %}
{% load blog_extras %}

{% block content %}
    <h2>Votre flux</h2>
    {% for instance in page_obj %}
        {% if instance|model_type == 'Blog' %}
            {% include 'blog/partials/blog_snippet.html' with blog=instance %}
        {% elif instance|model_type == 'Photo' %}
            {% include 'blog/partials/photo_snippet.html' with blog=instance %}
        {% endif %}
    {% endfor %}
    <span>
        {% if page_obj.has_previous %}
            <a href="?page=1">« première</a>
            <a href="?page={{ page_obj.previous_page_number }}">précédente</a>
        {% endif %}
    
        <span>
            Page {{ page_obj.number }} sur {{ page_obj.paginator.num_pages }}.

        </span>
        {% if page_obj.has_next %}
            <a href="?page={{ page_obj.next_page_number }}">suivante</a>
            
            <a href="?page={{ page_obj.paginator.num_pages }}">dernière »</a>
        {% endif %}
    </span>
{% endblock content %}

À quoi ressemble notre page maintenant ? On croise les doigts ! 🤞

Capture de la page du flux avec navigation
Capture de la page du flux avec navigation

Joli ! Nous pouvons désormais accéder à tous les billets et photos par le biais de ces éléments de navigation.

Maintenant que vous les avez ajoutés au flux principal, il est temps de faire la même chose avec le flux photo.

C'est à vous ! Paginez le flux photo

Allez-y, paginez le flux photo !

Vous devrez :

  • Mettre à jour la vuephoto_feed pour créer une instance duPaginator  et inclure l’objetpage_obj  dans le contexte.

  • Mettre à jour lephoto_feed.htmlpour itérer danspage_objet non plus dans photos.

  • Ajouter la section de navigation en bas de page dans  photo_feed.html  — indice — il s’agit d’un élément réutilisable que vous avez partagé avec plusieurs gabarits. Savez-vous comment l’inclure dans les deux sans vous répéter ?

Et votre site est terminé ! Félicitations ! N’oubliez pas de comparer la solution que vous avez trouvée pour votre dernier exercice avec la solution dans le dépôt GitHub.

En résumé 

  • La pagination améliore la performance d’un site en divisant de gros itérables en morceaux plus petits.

  • Pour paginer une vue, donnez à la classe   Paginator  un itérable tel qu’un QuerySet ou une liste, ainsi que le nombre d’instances que vous voulez afficher par page. 

  • Accédez au numéro de page par une chaîne de requête et utilisez-le pour générer un  page_obj  que vous passerez au contexte du gabarit.

  • Utilisez un gabarit partiel pour inclure la section de navigation afin de paginer plusieurs pages.

Et maintenant que vous savez paginer les pages de votre site, le moment est venu de récapituler ce cours !  

Exemple de certificat de réussite
Exemple de certificat de réussite