# Documentation Django 5.2.8

# Le système des plans de site (`sitemap`)

Django est livré avec un système de génération de plans de site à haut niveau qui permet de créer des fichiers XML sitemap.

## Aperçu

Un plan de site « sitemap » est un fichier XML sur un site web indiquant aux robots des moteurs de recherche à quelle fréquence les pages changent et comment certaines pages « importantes » sont en relation avec d’autres pages du site. Cette information aide les moteurs de recherche à indexer un site.

L’application sitemap de Django automatise la création de ce fichier XML en permettant d’exprimer cette information sous forme de code Python.

Cela fonctionne un peu comme le système de syndication de Django. Pour créer un plan de site, écrivez une classe `Sitemap` et référencez-la dans la configuration d’URL.

## Installation

Pour installer l’application sitemap, procédez comme suit :

1. Ajoutez `'django.contrib.sitemaps'` au réglage `INSTALLED_APPS`.

2. Vérifiez la présence d’un moteur `DjangoTemplates``dont l'option ``APP_DIRS` vaut `True` dans le réglage `TEMPLATES`. Il y est par défaut, de sorte que vous aurez uniquement besoin de l’ajouter si vous avez modifié ce réglage.

3. Assurez-vous d’avoir installé le `gestionnaire de sites`.

(Remarque : l’application sitemap n’installe aucune table de base de données. La seule raison pour laquelle elle doit être présente dans `INSTALLED_APPS` est que la fonction de chargement des gabarits `Loader()` doit pouvoir trouver les gabarits par défaut.)

## Initialisation

views.sitemap(request, sitemaps, section=None, template_name='sitemap.xml', content_type='application/xml')

Pour activer la génération du plan du site d’un site Django, ajoutez cette ligne à la configuration d’URL:

    from django.contrib.sitemaps.views import sitemap

    path(
        "sitemap.xml",
        sitemap,
        {"sitemaps": sitemaps},
        name="django.contrib.sitemaps.views.sitemap",
    )

Cela indique à Django de construire un plan de site lorsqu’un client accède à `/sitemap.xml`.

Le nom du fichier sitemap n’est pas important, mais l’emplacement l’est. Les moteurs de recherche n’indexeront que les liens du plan de site à partir du niveau actuel de l’URL et en-dessous. Par exemple, si `sitemap.xml` réside dans le répertoire racine, il peut faire référence à n’importe quelle URL du site. Cependant, si le fichier sitemap réside dans `/content/sitemap.xml`, il ne peut référencer que des URL qui commencent par `/content/`.

La vue `sitemap` accepte un paramètre supplémentaire obligatoire : `{'sitemaps': sitemaps}`. `sitemaps` doit être un dictionnaire qui associe une étiquette de section courte (par exemple, `blog` ou `nouvelles`) à sa classe `Sitemap` (par exemple, `BlogSitemap` ou `NewsSitemap`). Il peut également s’appliquer à une instance de classe `Sitemap` (par exemple, `BlogSitemap(ma_variable)`).

## Classes `Sitemap`

Une classe `Sitemap` est une classe Python qui représente une « section » d’entrées dans votre plan de site. Par exemple, une classe `Sitemap` pourrait représenter toutes les entrées de votre blog, tandis qu’une autre pourrait représenter tous les évènements d’un calendrier d’évènements.

Dans le cas le plus simple, toutes ces sections sont regroupées dans un seul `sitemap.xml`, mais il est également possible d’utiliser le système pour générer un index de sitemap qui référence d’autres fichiers sitemap individuels, un par section (voir Création d’un index de plan de site ci-dessous).

Les classes `Sitemap` doivent être des sous-classes de `django.contrib.sitemaps.Sitemap`. Elles peuvent résider n’importe où dans votre code source.

## Un exemple

Supposons que vous avez un système de blog, avec un modèle `Entry`. Vous souhaitez que le plan de site contienne les liens vers tous les articles de blog. Voici à quoi la classe de plan de site pourrait ressembler :

    from django.contrib.sitemaps import Sitemap
    from blog.models import Entry

    class BlogSitemap(Sitemap):
        changefreq = "never"
        priority = 0.5

        def items(self):
            return Entry.objects.filter(is_draft=False)

        def lastmod(self, obj):
            return obj.pub_date

Remarque :

- `changefreq` et `priority` sont des attributs de classe correspondant respectivement aux éléments `<changefreq>` et `<priority>`. Il est possible qu’ils correspondent à des fonctions, comme pour `lastmod` dans l’exemple ci-dessus.

- `items()` is a method that returns a sequence or `QuerySet` of objects. The objects returned will get passed to any callable methods corresponding to a sitemap property (`location`, `lastmod`, `changefreq`, and `priority`).

- `lastmod` doit renvoyer un objet `datetime`.

- There is no `location` method in this example, but you can provide it in order to specify the URL for your object. By default, `location` calls `get_absolute_url()` on each object and returns the result.

## Référence de la classe `Sitemap`

class Sitemap

  Une classe `Sitemap` peut définir les méthodes/attributs suivants :

  items()

    Required. A method that returns a sequence or `QuerySet` of objects. The framework doesn’t care what type of objects they are; all that matters is that these objects get passed to the `location`, `lastmod`, `changefreq` and `priority` methods.

  location

    Facultatif. Soit une méthode, soit un attribut.

    If it’s a method, it should return the absolute path for a given object as returned by `items()`.

    If it’s an attribute, its value should be a string representing an absolute path to use for every object returned by `items()`.

    Dans les deux cas, « chemin absolu » signifie une URL qui ne comprend ni le protocole ni le domaine. Exemples :

    - Bon : `'/foo/bar/'`

    - Mauvais : `'example.com/foo/bar/'`

    - Mauvais : `'https://example.com/foo/bar/'`

    If `location` isn’t provided, the framework will call the `get_absolute_url()` method on each object as returned by `items`.

    Pour indiquer un protocole autre que `'http'`, utilisez `protocol`.

  lastmod

    Facultatif. Soit une méthode, soit un attribut.

    If it’s a method, it should take one argument – an object as returned by `items()` – and return that object’s last-modified date/time as a `datetime`.

    If it’s an attribute, its value should be a `datetime` representing the last-modified date/time for every object returned by `items()`.

    Si tous les éléments d’un plan de site possèdent `lastmod`, le plan de site généré par `views.sitemap()` comportera un en-tête `Last-Modified` égal à la valeur `lastmod` la plus récente. Vous pouvez activer l’intergiciel `ConditionalGetMiddleware` pour que Django réponde de manière appropriée aux requêtes contenant un en-tête `If-Modified-Since`, ce qui évitera d’envoyer le plan de site si celui-ci n’a pas changé.

  paginator

    Facultatif.

    This property returns a `Paginator` for `items()`. If you generate sitemaps in a batch you may want to override this as a cached property in order to avoid multiple `items()` calls.

  changefreq

    Facultatif. Soit une méthode, soit un attribut.

    If it’s a method, it should take one argument – an object as returned by `items()` – and return that object’s change frequency as a string.

    If it’s an attribute, its value should be a string representing the change frequency of every object returned by `items()`.

    Les valeurs possibles pour `changefreq`, que ce soit une méthode ou un attribut, sont :

    - `'always'` (toujours)

    - `'hourly'` (chaque heure)

    - `'daily'` (quotidiennement)

    - `'weekly'` (chaque semaine)

    - `'monthly'` (chaque mois)

    - `'yearly'` (annuellement)

    - `'never'` (jamais)

  priority

    Facultatif. Soit une méthode, soit un attribut.

    If it’s a method, it should take one argument – an object as returned by `items()` – and return that object’s priority as either a string or float.

    If it’s an attribute, its value should be either a string or float representing the priority of every object returned by `items()`.

    Exemples de valeurs pour `priority`: `0.4`, `1.0`. La priorité par défaut d’une page est de `0.5`. Voir la documentation de sitemaps.org pour plus d’informations.

  protocol

    Facultatif.

    Cet attribut définit le protocole (`'http'` ou `'https'`) des URL dans le plan du site. S’il n’est pas défini, le protocole avec lequel le plan du site a été demandé sera utilisé. Si le plan du site est construit en dehors du contexte d’une requête, la valeur par défaut est `'https'`.

  limit

    Facultatif.

    Cet attribut définit le nombre maximum d’URL incluses sur chaque page du plan de site. Sa valeur ne doit pas dépasser la valeur par défaut de `50000`, qui est la valeur limite supérieure autorisée par le protocole des plans de site.

  i18n

    Facultatif.

    Un attribut booléen qui définit si les URL de ce plan de site doivent être générées en utilisant toutes les langues de `LANGUAGES`. La valeur par défaut est `False`.

  languages

    Facultatif.

    Une suite de codes de langues à utiliser pour la génération de liens alternatifs lorsque `i18n` est activé. La valeur par défaut correspond à `LANGUAGES`.

  alternates

    Facultatif.

    Un attribut booléen. Lorsqu’il est est employé de concert avec `i18n`, les URL produites auront chacune une liste de liens alternatifs pointant vers d’autres versions linguistiques à l’aide de l”attribut hreflang. La valeur par défaut est `False`.

  x_default

    Facultatif.

    Un attribut booléen. Lorsqu’il vaut `True`, les liens alternatifs générés par `alternates` contiendront une entrée `hreflang="x-default"` avec la valeur `LANGUAGE_CODE`. La valeur par défaut est `False`.

  get_latest_lastmod()

    Facultatif. Une méthode qui renvoie la dernière valeur renvoyée par `lastmod`. Cette fonction est utilisée pour ajouter l’attribut `lastmod` aux variables de contexte de l’index de plan de site.

    Par défaut, `get_latest_lastmod()` renvoie :

    - Si `lastmod` est un attribut : `lastmod`.

    - If `lastmod` is a method: The latest `lastmod` returned by calling the method with all items returned by `items()`.

  get_languages_for_item(item)

    Facultatif Une méthode renvoyant la liste des codes de langues pour lesquels un élément est affiché. Par défaut, `get_languages_for_item()` renvoie `languages`.

## Raccourcis

L’infrastructure sitemap fournit une classe pratique pour un cas courant :

class GenericSitemap(info_dict, priority=None, changefreq=None, protocol=None)

  La classe `django.contrib.sitemaps.GenericSitemap` permet de créer un plan du site en lui passant un dictionnaire qui doit contenir au minimum une entrée `queryset`. Ce jeu de requête sera utilisé pour générer les éléments du plan du site. Le dictionnaire peut aussi contenir une clé `date_field` qui définit un champ de date pour les objets récupérés par `queryset`. Ce champ sera utilisé pour l’attribut `lastmod` et les méthodes `get_latest_lastmod()` dans le plan du site généré.

  Les paramètres nommés `priority`, `changefreq` et `protocol` permettent de définir ces attributs pour toutes les URL.

### Exemple

Voici un exemple de configuration d’URL utilisant `GenericSitemap`:

    from django.contrib.sitemaps import GenericSitemap
    from django.contrib.sitemaps.views import sitemap
    from django.urls import path
    from blog.models import Entry

    info_dict = {
        "queryset": Entry.objects.all(),
        "date_field": "pub_date",
    }

    urlpatterns = [
        # some generic view using info_dict
        # ...
        # the sitemap
        path(
            "sitemap.xml",
            sitemap,
            {"sitemaps": {"blog": GenericSitemap(info_dict, priority=0.6)}},
            name="django.contrib.sitemaps.views.sitemap",
        ),
    ]

## Plan de site pour les vues statiques

Il peut souvent être nécessaire de faire indexer par les robots des moteurs de recherche des vues qui ne sont ni des pages de détail d’un objet, ni des pages statiques. La solution est de fournir une liste explicite de noms d’URL pour ces vues dans `items` et d’appeler `reverse()` dans la méthode `location` du sitemap. Par exemple :

    # sitemaps.py
    from django.contrib import sitemaps
    from django.urls import reverse

    class StaticViewSitemap(sitemaps.Sitemap):
        priority = 0.5
        changefreq = "daily"

        def items(self):
            return ["main", "about", "license"]

        def location(self, item):
            return reverse(item)

    # urls.py
    from django.contrib.sitemaps.views import sitemap
    from django.urls import path

    from .sitemaps import StaticViewSitemap
    from . import views

    sitemaps = {
        "static": StaticViewSitemap,
    }

    urlpatterns = [
        path("", views.main, name="main"),
        path("about/", views.about, name="about"),
        path("license/", views.license, name="license"),
        # ...
        path(
            "sitemap.xml",
            sitemap,
            {"sitemaps": sitemaps},
            name="django.contrib.sitemaps.views.sitemap",
        ),
    ]

## Création d’un index de plan de site

views.index(request, sitemaps, template_name='sitemap_index.xml', content_type='application/xml', sitemap_url_name='django.contrib.sitemaps.views.sitemap')

Le système sitemap a également la possibilité de créer un index de plan de site qui référence des fichiers sitemap individuels, un pour chaque section définie dans le dictionnaire `sitemaps`. Les seules différences dans l’utilisation sont les suivantes :

- Vous utilisez deux vues dans la configuration d’URL : `django.contrib.sitemaps.views.index()` et `django.contrib.sitemaps.views.sitemap()`.

- La vue `django.contrib.sitemaps.views.sitemap()` doit accepter un paramètre nommé `section`.

Voici à quoi ressembleraient les lignes appropriées de la configuration d’URL pour l’exemple ci-dessus :

    from django.contrib.sitemaps import views

    urlpatterns = [
        path(
            "sitemap.xml",
            views.index,
            {"sitemaps": sitemaps},
            name="django.contrib.sitemaps.views.index",
        ),
        path(
            "sitemap-<section>.xml",
            views.sitemap,
            {"sitemaps": sitemaps},
            name="django.contrib.sitemaps.views.sitemap",
        ),
    ]

Cela générera automatiquement un fichier `sitemap.xml` faisant référence à la fois à `sitemap-flatpages.xml` et à `sitemap-blog.xml`. Les classes `Sitemap` et le dictionnaire `sitemaps` ne changent aucunement.

If all sitemaps have a `lastmod` returned by `get_latest_lastmod()` the sitemap index will have a `Last-Modified` header equal to the latest `lastmod`.

Vous devriez créer un fichier d’index lorsqu’un plan de site contient plus de 50 000 URL. Dans ce cas, Django pagine automatiquement le plan du site et l’index reflétera cette situation.

Si vous n’utilisez pas la vue sitemap ordinaire – par exemple, si elle est enveloppée par un décorateur de mise en cache – vous devez nommer votre vue sitemap et passer `sitemap_url_name` à la vue d’index :

    from django.contrib.sitemaps import views as sitemaps_views
    from django.views.decorators.cache import cache_page

    urlpatterns = [
        path(
            "sitemap.xml",
            cache_page(86400)(sitemaps_views.index),
            {"sitemaps": sitemaps, "sitemap_url_name": "sitemaps"},
        ),
        path(
            "sitemap-<section>.xml",
            cache_page(86400)(sitemaps_views.sitemap),
            {"sitemaps": sitemaps},
            name="sitemaps",
        ),
    ]

## Personnalisation de gabarit

Si vous souhaitez utiliser un gabarit différent pour chaque plan de site ou d’index de plan de site disponible sur un site, vous pouvez l’indiquer en passant un paramètre `template_name` aux vues `sitemap` et `index` via la configuration d’URL :

    from django.contrib.sitemaps import views

    urlpatterns = [
        path(
            "custom-sitemap.xml",
            views.index,
            {"sitemaps": sitemaps, "template_name": "custom_sitemap.html"},
            name="django.contrib.sitemaps.views.index",
        ),
        path(
            "custom-sitemap-<section>.xml",
            views.sitemap,
            {"sitemaps": sitemaps, "template_name": "custom_sitemap.html"},
            name="django.contrib.sitemaps.views.sitemap",
        ),
    ]

Ces vues renvoient des instances `TemplateResponse` permettant de personnaliser facilement les données de réponse avant le processus de rendu. Pour plus de détails, consultez la documentation de TemplateResponse.

### Variables de contexte

Lors de la personnalisation des gabarits pour les vues `index()` et `sitemap()`, vous pouvez compter sur les variables de contexte suivantes.

### Accueil

La variable `sitemaps` est une liste d’objets contenant les attributs `location` et `lastmod` pour chaque plan de site. Chaque URL expose les attributs suivants :

- `location`: l’emplacement (URL et page) du plan de site.

- `lastmod`: rempli par la méthode `get_latest_lastmod()` pour chaque plan de site.

### Sitemap

La variable `urlset` est une liste d’URL devant apparaître dans le plan du site. Chaque URL expose des attributs tels que définis dans la classe `Sitemap`:

- `alternates`

- `changefreq` (fréquence de modification)

- `item` (élément)

- `lastmod` (date de dernière modification)

- `location` (adresse)

- `priority` (priorité)

L’attribut `alternates` est disponible lorsque `i18n` et `alternates` sont activés. Il s’agit d’une liste d’autres versions linguistiques, y compris la valeur par défaut facultative `x_default`, pour chaque URL. Chaque `alternate` est un dictionnaire avec les clés `location` et `lang_code`.

The `item` attribute has been added for each URL to allow more flexible customization of the templates, such as Google news sitemaps. Assuming Sitemap’s `items()` would return a list of items with `publication_data` and a `tags` field something like this would generate a Google News compatible sitemap:

    <?xml version="1.0" encoding="UTF-8"?>
    <urlset
      xmlns="https://www.sitemaps.org/schemas/sitemap/0.9"
      xmlns:news="https://www.google.com/schemas/sitemap-news/0.9">
    {% spaceless %}
    {% for url in urlset %}
      <url>
        <loc>{{ url.location }}</loc>
        {% if url.lastmod %}<lastmod>{{ url.lastmod|date:"Y-m-d" }}</lastmod>{% endif %}
        {% if url.changefreq %}<changefreq>{{ url.changefreq }}</changefreq>{% endif %}
        {% if url.priority %}<priority>{{ url.priority }}</priority>{% endif %}
        <news:news>
          {% if url.item.publication_date %}<news:publication_date>{{ url.item.publication_date|date:"Y-m-d" }}</news:publication_date>{% endif %}
          {% if url.item.tags %}<news:keywords>{{ url.item.tags }}</news:keywords>{% endif %}
        </news:news>
       </url>
    {% endfor %}
    {% endspaceless %}
    </urlset>