• 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

Affichez des billets et photos sur le flux

Utilisez des filtres personnalisés dans les gabarits

Maintenant que nos instances  Photo  et   Blog  sont classées dans une liste, nous pouvons les afficher dans le flux. Comment ? La réponse en vidéo.

Commençons par mettre à jour le gabarit   home.html  pour itérer dans l’ensemble de la nouvelle liste des instances   Photo  et   Blog  :

# blog/templates/blog/home.html
{% extends 'base.html' %}
{% block content %}
    <h2>Votre flux</h2>
    {% for instance in photos_and_blogs %}
        ...
    {% endfor %}
{% endblock content %}

Nous voulons afficher les  Blog  et   Photo  différemment. Il nous faut donc un moyen de distinguer entre les différents types d’objet dans le gabarit.

En Python pur, vous pourriez vérifier le  type()  de l’objet, comme ceci :

if type(instance) is models.Blog:
    # Traitement d’un billet de blog

Mais lorsque vous utilisez le langage de gabarit Django, vous n’avez pas accès aux fonctions standards de Python telles que  type(). Donc, pour récupérer le type de modèle, vous devez écrire un filtre personnalisé.

Lorsque vous créez des balises et gabarits personnalisés, spécifiez-les dans un répertoire  templatetags  dans une application Django. Cela permettra à Django de les intégrer automatiquement. Vous devez également inclure un  fichier   __init__.py  vide, afin que le répertoire  templatetags  soit considéré comme un package Python.

Ajoutons un filtre personnalisé dans un fichier nommé  blog_extras.py   .

(ENV) ~/fotoblog (master)
→ mkdir blog/templatetags
(ENV) ~/fotoblog (master)
→ touch blog/templatetags/__init__.py
(ENV) ~/fotoblog (master)
→ touch blog/templatetags/blog_extras.py

Un filtre personnalisé peut prendre un ou deux arguments. Tout ce que la fonction renvoie est affiché dans le gabarit comme résultat du filtre appliqué.

Dans notre cas, nous allons utiliser le filtre pour renvoyer une représentation en chaîne de caractères du type de modèle auquel l’instance appartient. Cela nécessitera seulement de fournir un argument, l’instance.

# blog/templatetags/blog_extras.py

def model_type(instance):
    return type(instance).__name__

 Pour garantir l’accessibilité de ces filtres dans les gabarits, créez une instance deLibrary  que vous nommerezregisteret enregistrez-y les filtres avec le décorateur@register.filter.

# blog/templatetags/blog_extras.py
from django import template

register = template.Library()

 
@register.filter
def model_type(value):
    return type(value).__name__

À présent que vous avez le filtre, vous pouvez l’utiliser pour distinguer les types d’objets dans le gabarit.

Utilisez la syntaxe suivante pour utiliser le filtre :

{{ instance|model_type }}

 Elle donnera comme résultat soit  'Blog'  , soit   'Photo'  .

Nous voulons utiliser ce résultat dans une instruction  if  , pour déterminer s’il faut afficher une photo ou un billet de blog. Avec le langage de gabarit de Django, on peut créer des instructions conditionnelles avec la balise   {% if <condition> %}  . Vous pouvez également utiliser nos filtres dans cette balise.

Pour utiliser notre balise personnalisée dans un gabarit, nous devons la charger dans le contexte du gabarit avec la balise{% load %}. Dans notre cas, nous ajoutons{% load blog_extras %}.

Pour utiliser la balise dans le gabarit de la page d’accueil, ajoutez :

{% extends 'base.html' %}
{% load blog_extras %}
{% block content %}
    <h2>Votre flux</h2>
    <div class="grid-container">
        {% for instance in blogs_and_photos %}
            {% if instance|model_type == 'Blog' %}
                // Billet affiché ici
            {% elif instance|model_type == 'Photo' %}
                // Photo affichée ici
            {% endif %}
        {% endfor %}
    </div>
{% endblock content %}

Ajoutez le HTML nécessaire pour afficher les billets de blog et les photos :

{% extends 'base.html' %}
{% load blog_extras %}
{% block content %}
    <h2>Votre flux</h2>
    <div class="grid-container">
        {% for instance in blogs_and_photos %}
            {% if instance|model_type == 'Blog' %}
                <div class="post">
                    <a href="{% url 'view_blog' instance.id %}">
                        <h4>Billet : {{ instance.title }}</h4>
                        <img src="{{ instance.photo.image.url }}">
                        <p><strong>Écrit par {{ instance.contributors.all|join:", " }}</strong></p>
                        <p>{{ instance.date_created }}</p>
                    </a>
                </div>
            {% elif instance|model_type == 'Photo' %}
                <div class="post">
                    <img src="{{ instance.image.url }}">
                    <p>{{ instance.caption }}</p>
                    <p><strong>Prise par {{ instance.uploader }}</strong></p>
                    <p>{{ instance.date_created }}</p>
                </div>
            {% endif %}
        {% endfor %}
    </div>
{% endblock content %}

Voyons à quoi ça ressemble dans le navigateur !

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

Il a l’air bien, même s’il y a quelques trucs que l’on peut améliorer. Regardons-les maintenant !

Utilisez des balises personnalisées dans les gabarits

Pour l’instant, le nom d’utilisateur de chaque personne effectuant un téléversement (les « uploaders ») se trouve à côté de chaque photo. C’est acceptable, mais nous voulons un affichage plus dynamique ! La solution en vidéo :

Au lieu de voir « Prise par <votre-username> », ce serait agréable de voir « Prise par vous. »

Pour faire ce changement, utilisez une balise personnalisée.

Les balises personnalisées sont similaires aux filtres personnalisés, mais elles utilisent la syntaxe  {% %}.

Accédons au contexte du gabarit dans notre balise personnalisée, et utilisons-le pour afficher soit « vous », soit le nom d’utilisateur de la personne qui a posté, en fonction de qui est connecté.

Pour enregistrer une fonction en tant que balise personnalisée, utilisez le décorateur   @register.simple_tag. Pour inclure le contexte du gabarit dans la balise, passez l’argument  takes_context=True. En ajoutant ce flag, le premier argument de la fonction de la balise doit être nommé « context ».

Écrivons une balise personnalisée. Tout ce que la balise renverra sera affiché dans le gabarit lorsque nous l’utiliserons.

from django import template

register = template.Library()

@register.simple_tag(takes_context=True)
    def get_poster_display(context, user):
        if user == context['user']:
            return 'vous'
        return user.username

Et maintenant, incorporez-la dans la vue :

{% extends 'base.html' %}
{% load blog_extras %}
{% block content %}
    <h2>Votre flux</h2>
    <div class="grid-container">
        {% for instance in blogs_and_photos %}
            // Billet affiché ici
            {% elif instance|model_type == 'Photo' %}
                <div class="post">
                    <img src="{{ instance.image.url }}">
                    <p>{{ instance.caption }}</p>
                    <p><strong>Taken by {% get_poster_display instance.uploader %}
</strong></p>

                    <p>{{ instance.date_created }}</p>
                </div>
            {% endif %}
        {% endfor %}
    </div>
{% endblock content %}

Et vous pouvez regarder à quoi ça ressemble !

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

Ça a meilleure allure, mais le format des dates mériterait d'être amélioré. Vous allez maintenant créer votre propre filtre pour les afficher correctement.

C'est à vous ! Créez votre propre filtre personnalisé

Affichez une chaîne de façon dynamique, en fonction de la date d’ajout d’un post.

Vous allez devoir :

  • Créer un filtre nommé   get_posted_at_display  prenant un argument,time.

  • Comparer la valeur avec celle dedjango.utils.timezone.now(). Ça renvoie une date et une heure prenant en compte le fuseau horaire du serveur, et doit être utilisé sur  datetime.datetime.now().

  • Renvoyer une chaîne en fonction des conditions suivantes :

    • 0 < x < 60 minutes —  'Posté il y a x minutes'

    • 1 < x < 24 heures —   'Posté il y a x heures'

    • x > 24 heures —   'Posté à HH:MM jj mm aa, par exemple17:53 04 Avr 21. Utilisezstrftimepour créer cette chaîne.

  • Utiliser votre nouveau filtre pour afficher l’heure à laquelle le billet ou la photo a été publié sur le fil d’actualité.

Lorsque vous aurez ajouté votre filtre personnalisé, comparez-le avec la solution dans le dépôt GitHub.

Maintenant que nous avons construit le fil d’actualité, nettoyons le gabarit et créons des éléments de gabarit réutilisables avec la balise  {% include %}  .

Utilisez des gabarits partiels réutilisables avec la balise {% include %}  

Nous avons déjà utilisé la balise  {% extends %}  pour permettre à chaque gabarit du site d’être construit à partir d’un gabarit de base réutilisable.

Vous pouvez également utiliser la balise  {% include %}  pour créer des éléments réutilisables, pouvant être répétés dans plusieurs gabarits.

En construisant notre flux, nous voulons afficher chaque billet de blog et chaque photo de la même manière à chaque fois. Nous voudrons aussi peut-être afficher nos billets de blog et photos dans différentes parties du site. Pour faire cela, il nous faut créer un gabarit partiel. Découvrez de quelle manière en vidéo :

Nous allons stocker nos gabarits partiels dans  blog/templates/blog/partials/  .

Tout d’abord, créons un gabarit partiel pour afficher une instance deBlog  nommé   blog_snippet.html   .

Créez cet extrait tout comme un gabarit normal. Vous pouvez copier le segment de gabarit de votre gabarit de flux, mais vu que vous travaillez avec une instance deBlog, renommez   instance  en  blog.

{% load blog_extras %}
<div class="post">
    <a href="{% url 'view_blog' blog.id %}">
        <h4>Billet : {{ blog.title }}</h4>
        <img src="{{ blog.photo.image.url }}">
        <p><strong>Écrit par {{ blog.contributors.all|join:", " }}</strong></p>
        <p>{{ blog.date_created|get_posted_at_display }}</p>
    </a>
</div>

 Incluez maintenant l’extrait de blog dans le gabarit du flux, en utilisant le mot-clé   with  pour renommer la variable   instance  en   blog  dans le gabarit partiel.

Le remplacement de la section de blog du gabarit du flux par l’extrait ressemble à ça :

{% extends 'base.html' %}
{% load blog_extras %}
{% block content %}
    <h2>Votre flux</h2>
    <div class="grid-container">
        {% for instance in blogs_and_photos %}
            {% if instance|model_type == 'Blog' %}
                {% include 'blog/partials/blog_snippet.html' with blog=instance %}
            {% elif instance|model_type == 'Photo' %}
             ...
            {% endif %}
        {% endfor %}
    </div>
{% endblock content %}

Voyons à quoi ressemble le flux lorsqu’il utilise un extrait.

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

C’est exactement pareil ! Tout fonctionne comme prévu.

L’avantage d’utiliser un gabarit partiel, comme celui-ci, est que vous pouvez réutiliser cet extrait dans n’importe quel gabarit de votre site. Cela rend aussi le gabarit d’origine plus propre et plus lisible.

Vous allez ensuite faire la même chose avec la section photo. Puis, vous allez utiliser cet extrait pour créer le flux photo.

C'est à vous ! Créez un gabarit partiel pour afficher une photo

Maintenant que vous avez appris à utiliser un gabarit partiel pour afficher une instance de   Blog, à vous de jouer pour faire la même chose avec une  Photo  .

Vous pouvez utiliser cet extrait dans les flux standard et photo.

Vous allez devoir :

  • Créer un nouveau gabarit partiel dans   blog/templates/blog/partials/photo_snippet.html  .

  • Copier la section photo actuelle de   feed.htmlàphoto_snippet.html  .

  • Utiliser la balise{% include %}pour inclurephoto_snippet.html  dans  feed.html.

  • Créer le flux photo à partir dephoto_feed.html . Réutiliserphoto_snippet.html  dans ce gabarit en utilisant la balise{% include %}.

  • Inclure le flux photo dans les modèles d’URL et ajouter un lien vers celui-ci dans la barre latérale.

Une fois que vous aurez fini, vous pourrez comparer votre code avec la solution dans le dépôt GitHub.

En résumé 

  • Créez et enregistrez des filtres et des balises personnalisés pour créer des fonctions utilitaires que vous pourrez utiliser dans les gabarits, présentant les objets et attributs de façon répétable.

  • Utilisez la balise  {% include %}   pour créer des éléments réutilisables dans vos gabarits.

Maintenant que vous avez affiché tous les billets et photos dans le flux, voyons comment améliorer la performance et la facilité d’utilisation de la page grâce à la pagination.

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