Templates Django

Le système de gabarits de Django (Template System) est un composant central utilisé pour séparer la logique métier (Python) de la couche de présentation (HTML). Il permet aux développeurs de générer dynamiquement des pages HTML à l'aide de balises et de variables simples.

Dans le chapitre précédent, nous avons utilisédjango.http.HttpResponse()pour produire"Hello World!"Cette approche mélange les données et les vues, ce qui n'est pas conforme à la philosophie MVT de Django.

Dans cette section, nous allons présenter en détail l'application des gabarits Django. Un gabarit est un texte utilisé pour séparer la forme de présentation et le contenu d'un document.

FonctionnalitésSyntaxe/ExemplesScénarios applicables
Rendu des variables{{ variable }}Afficher dynamiquement les données
Contrôle logique{% if %}, {% for %}Rendu conditionnel/boucle
Héritage de modèle{% extends %}, {% block %}Éviter les structures HTML en double
Fichiers statiques{% static 'path' %}Charger CSS/JS/images
Filtres personnalisés@register.filterÉtendre les fonctionnalités des modèles

Exemples d'application de modèle

En poursuivant avec le projet du chapitre précédent, nous allons créer un répertoire templates sous le répertoire HelloWorld et créer un fichier example.html. La structure complète du répertoire est la suivante :

HelloWorld/
|-- HelloWorld
|   |-- __init__.py
|   |-- __init__.pyc
|   |-- settings.py
|   |-- settings.pyc
|   |-- urls.py
|   |-- urls.pyc
|   |-- views.py
|   |-- views.pyc
|   |-- wsgi.py
|   `-- wsgi.pyc
|-- manage.py
`-- templates
    `-- example.html

Le code du fichier example.html est le suivant :

Code du fichier HelloWorld/templates/example.html :

<h1>{{ hello }}</h1>

D'après les modèles, nous savons que les variables utilisent des doubles accolades.{{ }}。

Ensuite, nous devons indiquer le chemin du fichier modèle à Django. Ouvrez le fichier HelloWorld/HelloWorld/settings.py et modifiezTEMPLATESdansDIRSen[BASE_DIR / "templates"], comme indiqué ci-dessous :

Code du fichier HelloWorld/HelloWorld/settings.py :

...
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR / "templates"],       # Modifier ici
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]
...

Nous modifions maintenant views.py pour ajouter un nouvel objet afin de soumettre des données au template :

Code du fichier HelloWorld/HelloWorld/views.py :

from django.shortcuts import render def example(request): context = {} context['hello'] = 'Bonjour le monde !' return render(request, 'example.html', context)

Comme vous pouvez le voir, nous utilisons render ici pour remplacer le HttpResponse utilisé précédemment. render prend également un dictionnaire context comme paramètre.

Les paires clé-valeur des éléments dans le dictionnaire context.helloCorrespond aux variables dans le gabarit{{ hello }}。

Code du fichier HelloWorld/HelloWorld/urls.py :

from django.contrib import admin from django.urls import path from . import views urlpatterns = [ path('admin/', admin.site.urls), path('example/', views.example), ]

Ensuite, entrez dans le répertoire HelloWorld et exécutez la commande suivante pour démarrer le serveur :

python3 manage.py runserver 0.0.0.0:8000

Visitez à nouveauhttp://127.0.0.1:8000/example, vous pouvez voir la page :

De cette façon, nous avons fini d'utiliser des gabarits pour produire des données, réalisant ainsi la séparation des données et des vues.

Ensuite, nous présenterons spécifiquement les règles de syntaxe couramment utilisées dans les gabarits.


Balises de gabarit Django

Syntaxe :

{% tag %}

Contrôler la logique des gabarits, balises courantes :

BalisesObjectif
{% for %}Parcourir des listes/dictionnaires
{% if %}Instruction conditionnelle
{% extends %}Hériter du gabarit de base
{% block %}Définir des blocs de contenu qui peuvent être surchargés par les gabarits enfants
{% include %}Intégrer d'autres fragments de gabarit
{% url %}Résolution inverse des URL (pour éviter les chemins codés en dur)
{% csrf_token %}Générer un jeton CSRF (pour les formulaires POST)

Variable

Syntaxe des gabarits :

view:{"HTML变量名" : "views变量名"}
HTML:{{变量名}}

Code du fichier HelloWorld/HelloWorld/views.py :

from django.shortcuts import render

def example(request):
  views_name = "Example"
  return  render(request,"example.html", {"name":views_name})

example.html dans templates :

<p>{{ name }}</p>

Visitez à nouveau http://127.0.0.1:8000/example, et vous pouvez voir la page :

Liste

Dans example.html dans templates, vous pouvez utiliser.pour récupérer l'élément correspondant par indice.

Code du fichier HelloWorld/HelloWorld/views.py :

from django.shortcuts import render

def example(request):
    views_list = ["Tutoriel débutant 1","Tutoriel débutant 2","Tutoriel débutant 3"]
    return render(request, "example.html", {"views_list": views_list})

Code du fichier HelloWorld/templates/example.html :

<p>{{ views_list }}</p># Récupérer toute la liste<p>{{ views_list.0 }}</p># Prendre le premier élément de la liste

Visitez à nouveau http://127.0.0.1:8000/example, et vous pouvez voir la page :

Dictionnaire

Dans example.html dans templates, vous pouvez utiliser.keypour récupérer la valeur correspondante.

Code du fichier HelloWorld/HelloWorld/views.py :

from django.shortcuts import render

def example(request):
    views_dict = {"name":"Exemple"}
    return render(request, "example.html", {"views_dict": views_dict})

Code du fichier HelloWorld/templates/example.html :

<p>{{ views_dict }}</p> <p>{{ views_dict.name }}</p>

Visitez à nouveau http://127.0.0.1:8000/example, et vous pouvez voir la page :

Filter

Syntaxe des gabarits :
{{ Variable name | Filter: optional parameter }}

Les filtres de template peuvent modifier une variable avant son affichage. Les filtres utilisent le caractère pipe, comme indiqué ci-dessous :

{{ name|lower }}

Après que la variable {{ name }} est traitée par le filtre lower, le texte est converti de majuscules en minuscules.

Les pipes de filtres peuvent être *chaînés*, c'est-à-dire que la sortie d'un pipe de filtre peut servir d'entrée au pipe suivant :

{{ my_list|first|upper }}

L'exemple ci-dessus prend le premier élément et le convertit en majuscules.

Certains filtres ont des paramètres. Les paramètres de filtre suivent après un deux-points et sont toujours entre guillemets doubles. Par exemple :

{{ bio|truncatewords:"30" }}

Cela affichera les 30 premiers mots de la variable bio.

Autres filtres :

  • addslashes : Ajoute des barres obliques inverses devant toute barre oblique inverse, tout guillemet simple ou tout guillemet double.
  • date : Formate un objet date ou datetime selon le paramètre de chaîne de format spécifié. Exemple :
    {{ pub_date|date:"F j, Y" }}
  • length : Renvoie la longueur de la variable.

default

default fournit une valeur par défaut pour la variable.

Si la valeur booléenne de la variable transmise par les vues est false, la valeur par défaut spécifiée est utilisée.

Les valeurs suivantes sont false :

0  0.0  False  0j  ""  []  ()  set()  {}  None

Code du fichier HelloWorld/HelloWorld/views.py :

from django.shortcuts import render

def example(request):
    name =0
    return render(request, "example.html", {"name": name})

Code du fichier HelloWorld/templates/example.html :

{{ name|default:"Rookie Tutorial 666" }}

Visitez à nouveau http://127.0.0.1:8000/example, et vous pouvez voir la page :

longueur

Renvoie la longueur de l’objet, applicable aux chaînes de caractères et aux listes.

Pour un dictionnaire, il renvoie le nombre de paires clé-valeur ; pour un ensemble, il renvoie la longueur après déduplication.

Code du fichier HelloWorld/HelloWorld/views.py :

from django.shortcuts import render

def example(request):
    name ="Exemple"
    return render(request, "example.html", {"name": name})

Code du fichier HelloWorld/templates/example.html :

{{ name|length}}

Visitez à nouveau http://127.0.0.1:8000/example, et vous pouvez voir la page :

filesizeformat

Affiche la taille du fichier dans un format plus lisible (c.-à-d. '13 KB', '4.1 MB', '102 bytes', etc.).

Pour un dictionnaire, il renvoie le nombre de paires clé-valeur ; pour un ensemble, il renvoie la longueur après déduplication.

Code du fichier HelloWorld/HelloWorld/views.py :

from django.shortcuts import render

def example(request):
    num=1024
    return render(request, "example.html", {"num": num})

Code du fichier HelloWorld/templates/example.html :

{{ num|filesizeformat}}

Visitez à nouveau http://127.0.0.1:8000/example, et vous pouvez voir la page :

date

Formate une variable de date selon un format donné.

FormatageY-m-d H:i:sreturnAnnée-Mois-Jour Heure:Minute:Secondeheure au format de.

Code du fichier HelloWorld/HelloWorld/views.py :

from django.shortcuts import render

def example(request):
    import datetime
    now  =datetime.datetime.now()
    return render(request, "example.html", {"time": now})

Code du fichier HelloWorld/templates/example.html :

{{ time|date:"Y-m-d" }}

Visitez à nouveau http://127.0.0.1:8000/example, et vous pouvez voir la page :

truncatechars

Si le nombre total de caractères dans une chaîne dépasse le nombre spécifié, la partie finale sera tronquée.

La chaîne tronquée se terminera par...fin.

Code du fichier HelloWorld/HelloWorld/views.py :

from django.shortcuts import render

def example(request):
    views_str = "Example"
    return render(request, "example.html", {"views_str": views_str})

Code du fichier HelloWorld/templates/example.html :

{{ views_str|truncatechars:2}}

Visitez à nouveau http://127.0.0.1:8000/example, et vous pouvez voir la page :

safe

Marque une chaîne comme sûre et ne nécessite pas d’échappement.

N'utilisez le filtre safe que lorsque vous pouvez garantir que les données transmises depuis views.py sont absolument sûres.

Il a le même effet que mark_safe dans le fichier views.py du backend.

Django échappe automatiquement la syntaxe des balises transmise depuis views.py vers les fichiers HTML, ce qui rend sa sémantique inopérante. L'ajout du filtre safe indique à Django que les données sont sûres et n'ont pas besoin d'être échappées, permettant à la sémantique des données de prendre effet.

Code du fichier HelloWorld/HelloWorld/views.py :

from django.shortcuts import render

def example(request):
    views_str = "<a href='/index.html'>Cliquez pour accéder</a>"
    return render(request, "example.html", {"views_str": views_str})

Code du fichier HelloWorld/templates/example.html :

{{ views_str|safe }}

Visitez à nouveau http://127.0.0.1:8000/example, et vous pouvez voir la page :

balise if/else

Le format de syntaxe de base est le suivant :

{% if condition %}
     ... display
{% endif %}

Ou :

{% if condition1 %}
   ... display 1
{% elif condition2 %}
   ... display 2
{% else %}
   ... display 3
{% endif %}

Détermine s'il faut afficher en fonction de conditions. if/else prend en charge l'imbrication.

La balise {% if %} accepte les mots-clés and, or et not pour évaluer plusieurs variables, ou pour nier une variable (not), par exemple :

{% if athlete_list and coach_list %}
     athletes 和 coaches 变量都是可用的。
{% endif %}

Code du fichier HelloWorld/HelloWorld/views.py :

from django.shortcuts import render

def example(request):
    views_num = 88
    return render(request, "example.html", {"num": views_num})

Code du fichier HelloWorld/templates/example.html :

{%if num > 90 and num <= 100%} Excellent {%elif num > 60 and num <= 90%} Qualifié {%else%} Allez jouer~ {%endif %}

Visitez à nouveau http://127.0.0.1:8000/example, et vous pouvez voir la page :

balise for

{% for %} nous permet d'itérer sur une séquence.

Semblable au cas de l'instruction for de Python, la syntaxe de boucle est for X in Y, où Y est la séquence à parcourir et X est le nom de la variable utilisé dans chaque boucle donnée.

À chaque boucle, le système de gabarits affichera tout le contenu entre{% for %}et{% endfor %}.

Par exemple, étant donné une variable de liste d'athlètes athlete_list, nous pouvons utiliser le code suivant pour afficher cette liste :
<ul>
{% for athlete in athlete_list %}
    <li>{{ athlete.name }}</li>
{% endfor %}
</ul>

Code du fichier HelloWorld/HelloWorld/views.py :

from django.shortcuts import render

def example(request):
    views_list = ["Example","Rookie Tutorial 1","Rookie Tutorial 2","Rookie Tutorial 3",]
    return render(request, "example.html", {"views_list": views_list})

Code du fichier HelloWorld/templates/example.html :

{% for i in views_list %} {{ i }} {% endfor %}

Visitez à nouveau http://127.0.0.1:8000/example, et vous pouvez voir la page :

Ajoutez reversed à la balise pour que la liste s'itère en sens inverse :

{% for athlete in athlete_list reversed %}
...
{% endfor %}

Code du fichier HelloWorld/templates/example.html :

{% for i in views_list reversed%} {{ i }} {% endfor %}

Visitez à nouveau http://127.0.0.1:8000/example, et vous pouvez voir la page :

Parcourir un dictionnaire: Vous pouvez directement utiliser un dictionnaire.itemsMéthode : utilisez le dépaquetage de variables pour obtenir les clés et les valeurs séparément.

Code du fichier HelloWorld/HelloWorld/views.py :

from django.shortcuts import render

def example(request):
    views_dict = {"name":"Example","age":18}
    return render(request, "example.html", {"views_dict": views_dict})

Code du fichier HelloWorld/templates/example.html :

{% for i,j in views_dict.items %} {{ i }}---{{ j }} {% endfor %}

Visitez à nouveau http://127.0.0.1:8000/example, et vous pouvez voir la page :

Dans la balise {% for %}, vous pouvez obtenir l'index de boucle via la variable {{forloop}}.
  • forloop.counter : Obtient l'index de boucle dans l'ordre, en commençant à 1.
  • forloop.counter0 : Obtient l'index de boucle dans l'ordre, en commençant à 0.
  • forloop.revcounter : Obtient l'index de boucle en sens inverse, avec l'index final étant 1.
  • forloop.revcounter0 : Obtient l'index de boucle dans l'ordre inverse, l'index final étant 0.
  • forloop.first (généralement utilisé avec la balise if) : Renvoie True pour le premier élément, False pour les autres.
  • forloop.last (généralement utilisé avec la balise if) : Renvoie True pour le dernier élément, False pour les autres.

Code du fichier HelloWorld/HelloWorld/views.py :

from django.shortcuts import render

def example(request):
     views_list = ["a", "b", "c", "d", "e"]
     return render(request, "example.html", {"listvar": views_list})

Code du fichier HelloWorld/templates/example.html :

{% for i in listvar %} {{ forloop.counter }} {{ forloop.counter0 }} {{ forloop.revcounter }} {{ forloop.revcounter0 }} {{ forloop.first }} {{ forloop.last }} {% endfor %}

Visitez à nouveau http://127.0.0.1:8000/example, et vous pouvez voir la page :

{% empty %}

Clause facultative {% empty %} : elle est exécutée lorsque la boucle est vide (c'est-à-dire lorsque la valeur booléenne de l'argument après in est False).

Code du fichier HelloWorld/HelloWorld/views.py :

from django.shortcuts import render

def example(request):
  views_list = []
  return render(request, "example.html", {"listvar": views_list})

Code du fichier HelloWorld/templates/example.html :

{% for i in listvar %} {{ forloop.counter0 }} {% empty %} VideVidePar exemple aussi~ {% endfor %}

Visitez à nouveau http://127.0.0.1:8000/example, et vous pouvez voir la page :

La balise {% for %} peut être imbriquée :

{% for athlete in athlete_list %}
    <h1>{{ athlete.name }}</h1>
    <ul>
    {% for sport in athlete.sports_played %}
        <li>{{ sport }}</li>
    {% endfor %}
    </ul>
{% endfor %}

Balise de commentaire

Les commentaires Django utilisent {# #}.

{# This is a comment #}

balise include

La balise {% include %} permet d'inclure le contenu d'autres modèles dans un modèle.

L'exemple suivant inclut le modèle nav.html :

{% include "nav.html" %}

csrf_token

csrf_token est utilisé dans les formulaires, et sa fonction est la protection contre la falsification de requête intersite.

Si non utilisée{% csrf_token %}balise : lors de l'utilisation d'un formulaire, si vous devez rediriger à nouveau vers une page, une erreur de permission 403 sera signalée.

Utilisée{% csrf_token %}balise : elle ne fonctionnera que lors de la soumission de données via un formulaire.

Analyse :

Tout d'abord, envoyez une requête au serveur pour obtenir la page de connexion. À ce stade, le middleware csrf générera automatiquement une balise input cachée. L'attribut value de cette balise est une chaîne aléatoire. Lorsque l'utilisateur obtient la page de connexion, il obtient également cette balise input cachée.

Ensuite, lorsque l'utilisateur doit utiliser un formulaire pour soumettre des données, il transportera cette balise input et la soumettra au middleware CSRF. La raison est que lorsqu'un formulaire soumet des données, il inclut toutes les balises input. Lorsque le middleware CSRF reçoit les données, il détermine si cette chaîne aléatoire est celle qu'il a envoyée à l'utilisateur pour la première fois. Si oui, la soumission des données réussit ; sinon, il renvoie une erreur de permission 403.


Balises et filtres personnalisés

1. Créez, dans le répertoire de l'application,templatetagsle répertoire (au même niveau que le répertoire templates, le nom du répertoire ne peut être que templatetags).

HelloWorld/
|-- HelloWorld
|   |-- __init__.py
|   |-- __init__.pyc
|   |-- settings.py
...
|-- manage.py
`-- templatetags
`-- templates

2. Créez n'importe quel fichier py dans le répertoire templatetags, par exemple :my_tags.py。

3. Le code du fichier my_tags.py est le suivant :

from django import template

register = template.Library()   #register的名字是固定的,不可改变

Modifiez la configuration de l'option TEMPLATES dans le fichier settings.py, et ajoutez la configuration libraries :

fichier de configuration settings.py

...
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR, "/templates",],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
            "libraries":{                          # Ajoutez ces trois lignes de configuration ici
                'my_tags':'templatetags.my_tags'   # Ajoutez ces trois lignes de configuration ici
            }                                      # Ajoutez ces trois lignes de configuration ici
        },
    },
]
...

4. Utilisez le décorateur @register.filter pour définir un filtre personnalisé.

Remarque :Le décorateur peut avoir au maximum 2 paramètres.

@register.filter
def my_filter(v1, v2):
    return v1 * v2

5. Utilisez le décorateur @register.simple_tag pour définir une balise personnalisée.

@register.simple_tag
def my_tag1(v1, v2, v3):
    return v1 * v2 * v3

6. Avant d'utiliser des balises et filtres personnalisés, vous devez importer ce fichier py tout en haut du body dans le fichier HTML.

{% load my_tags %}

7. Utilisez des filtres personnalisés en HTML.

{{ 11|my_filter:22 }}

8. Utiliser des balises personnalisées dans le HTML.

{% my_tag1 11 22 33 %}

9. Balises sémantiques

Importer mark_safe dans ce fichier py.

from django.utils.safestring import mark_safe

Lors de la définition de balises, utilisez la méthode mark_safe pour rendre les balises sémantiques, ce qui équivaut à la méthode html() dans jQuery.

Cela a le même effet que le filtre safe dans les fichiers HTML front-end.

@register.simple_tag
def my_html(v1, v2):
    temp_html = "<input type='text' id='%s' class='%s' />" %(v1, v2)
    return mark_safe(temp_html)

Utilisez cette balise personnalisée dans le HTML pour créer dynamiquement des balises sur la page.

{% my_html "zzz" "xxx" %}

Configurer les fichiers statiques

1. Créez un répertoire statics dans le répertoire racine du projet.

2. Ajoutez la configuration suivante en bas du fichier settings :

STATIC_URL = '/static/' # 别名 
STATICFILES_DIRS = [ 
    os.path.join(BASE_DIR, "statics"), 
]

3. Créez les répertoires css, js, images et plugins sous le répertoire statics, pour contenir respectivement les fichiers CSS, les fichiers JS, les images et les plugins.

4. Placez le framework Bootstrap dans le répertoire plugins.

5. Importez Bootstrap dans la balise head du fichier HTML.

Remarque :À ce stade, l'alias static du fichier de configuration doit être utilisé dans le chemin de référence, et non le répertoire statics.

<link rel="stylesheet" href="../static/plugins/bootstrap-3.3.7/dist/css/bootstrap.css.html">

Pour l'utiliser dans les gabarits, vous devez ajouter{% load static %}code. Dans l'exemple suivant, nous importons une image depuis le répertoire static.

Code du fichier HelloWorld/HelloWorld/views.py :

from django.shortcuts import render

def example(request):
    name ="Exemple"
    return render(request, "example.html", {"name": name})

Code du fichier HelloWorld/templates/example.html :

{% load static %} {{name}}<img src="{% static 'images/example-logo.png' %}" alt="example-logo">

Visitez à nouveau http://127.0.0.1:8000/example, et vous pouvez voir la page :


Héritage de modèle

Les gabarits peuvent permettre la réutilisation grâce à l'héritage, en réduisant le contenu redondant.

Le contenu de l'en-tête et du pied de page d'une page web est généralement cohérent, nous pouvons donc utiliser l'héritage de gabarits pour réaliser la réutilisation.

Le gabarit parent sert à placer le contenu réutilisable, et le gabarit enfant hérite du contenu du gabarit parent et place son propre contenu.

gabarit parent

Balise block...endblock :Les blocs réservés dans le gabarit parent sont laissés pour que le gabarit enfant les remplisse avec un contenu différencié. Les différents blocs réservés ne doivent pas avoir le même nom.

{% block 名称 %} 
预留给子模板的区域,可以设置设置默认内容
{% endblock 名称 %}

gabarit enfant

Le gabarit enfant utilise la balise extends pour hériter du gabarit parent :

{% extends "父模板路径"%} 

Si le gabarit enfant ne définit pas le contenu des blocs réservés du gabarit parent, le contenu par défaut défini dans le gabarit parent est utilisé. Bien sûr, vous pouvez aussi les laisser non définis, et ils seront vides.

Le gabarit enfant définit le contenu des blocs réservés du gabarit parent :

{ % block 名称 % }
内容 
{% endblock 名称 %}

Ensuite, nous créons d'abord un fichier base.html dans le répertoire templates du projet précédent. Le code est le suivant :

Code du fichier HelloWorld/templates/base.html :

<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Exemple (example.com)</title> </head> <body> <h1>Bonjour le monde !</h1> <p>Exemple de test Django.</p> {% block mainbody %} <p>original</p> {% endblock %} </body> </html>

Dans le code ci-dessus, la balise block nommée mainbody est la partie qui peut être remplacée par les héritiers.

Toutes les balises {% block %} indiquent au moteur de gabarit que les gabarits enfants peuvent surcharger ces parties.

Dans example.html, hériter de base.html et remplacer des blocs spécifiques. Le code modifié de example.html est le suivant :

Code du fichier HelloWorld/templates/example.html :

{%extends "base.html" %} {% block mainbody %} <p> Héritébase.htmlFichier</p> {% endblock %}

La première ligne de code indique que example.html hérite du fichier base.html. On peut voir que les balises block du même nom ici sont utilisées pour remplacer les blocs correspondants dans base.html.

Revisitez l'adresse http://127.0.0.1:8000/example, la sortie est la suivante :

autres extensions