| 1 |
============================================= |
|---|
| 2 |
Le framework pour les plans de site (sitemap) |
|---|
| 3 |
============================================= |
|---|
| 4 |
|
|---|
| 5 |
Django est fourni avec un puissant framework pour générer des |
|---|
| 6 |
plans de site permettant de créer facilement des fichiers |
|---|
| 7 |
XML Sitemap_. |
|---|
| 8 |
|
|---|
| 9 |
.. _Sitemap: http://www.sitemaps.org/ |
|---|
| 10 |
|
|---|
| 11 |
Présentation générale |
|---|
| 12 |
===================== |
|---|
| 13 |
|
|---|
| 14 |
Un plan de site est un fichier XML sur votre site web qui indique aux indexeurs |
|---|
| 15 |
des moteurs de recherche à quelle fréquence vos pages sont modifiées et l'importance |
|---|
| 16 |
de certaines pages par rapport à d'autres. Cette information permet aux moteurs |
|---|
| 17 |
de recherche d'indexer votre site. |
|---|
| 18 |
|
|---|
| 19 |
Le framework sitemap de Django automatise la création de ce fichier XML |
|---|
| 20 |
en vous permettant d'exprimer cette information en Python. |
|---|
| 21 |
|
|---|
| 22 |
Cela fonctionne d'une maniÚre assez similaire au `framework de syndication`_ de Django. |
|---|
| 23 |
Pour créer un plan de site, écrivez simplement une classe ``Sitemap`` et faites-y |
|---|
| 24 |
référence dans votre fichier URLconf_. |
|---|
| 25 |
|
|---|
| 26 |
.. _framework de syndication: ../syndication_feeds/ |
|---|
| 27 |
.. _URLconf: ../url_dispatch/ |
|---|
| 28 |
|
|---|
| 29 |
Installation |
|---|
| 30 |
============ |
|---|
| 31 |
|
|---|
| 32 |
Instructions pour installer l'application sitemap: |
|---|
| 33 |
|
|---|
| 34 |
1. Ajoutez le paramÚtre ``'django.contrib.sitemaps'`` à INSTALLED_APPS_. |
|---|
| 35 |
2. Vérifiez que le paramÚtre ``'django.template.loaders.app_directories.load_template_source'`` |
|---|
| 36 |
est bien présent dans TEMPLATE_LOADERS_. Il y est par défaut, |
|---|
| 37 |
vous ne devez donc y toucher que si vous l'avez déjà modifié. |
|---|
| 38 |
3. Assurez-vous d'avoir installé le `framework sites`_. |
|---|
| 39 |
|
|---|
| 40 |
(Note: L'application sitemap n'installe aucune table dans la base de |
|---|
| 41 |
données. La raison pour laquelle celle-ci doit être insérée dans ``INSTALLED_APPS`` |
|---|
| 42 |
est qu'il faut s'assurer que le chargeur de template (gabarit) puisse trouver les templates |
|---|
| 43 |
par défaut.) |
|---|
| 44 |
|
|---|
| 45 |
.. _INSTALLED_APPS: ../settings/#installed-apps |
|---|
| 46 |
.. _TEMPLATE_LOADERS: ../settings/#template-loaders |
|---|
| 47 |
.. _framework sites: ../sites/ |
|---|
| 48 |
|
|---|
| 49 |
Initialisation |
|---|
| 50 |
============== |
|---|
| 51 |
|
|---|
| 52 |
Pour activer la génération de plan de site sur votre site Django, |
|---|
| 53 |
ajoutez cette ligne à votre fichier URLconf_:: |
|---|
| 54 |
|
|---|
| 55 |
(r'^sitemap.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps}) |
|---|
| 56 |
|
|---|
| 57 |
Ceci indique à Django qu'il doit construire un plan de site lorsqu'un client accÚde à ``/sitemap.xml``. |
|---|
| 58 |
|
|---|
| 59 |
Le nom du fichier plan de site n'est pas important, mais sa position |
|---|
| 60 |
dans l'arborescence l'est. Les moteurs de recherche n'indexeront les liens |
|---|
| 61 |
de votre plan de site qu'à partir d'URL où il se trouve et en-dessous. Par exemple, |
|---|
| 62 |
si ``sitemap.xml`` appartient à votre répertoire racine, il peut référencer |
|---|
| 63 |
n'importe quelle URL de votre site. Par contre, si votre plan de site appartient |
|---|
| 64 |
à ``/content/sitemap.xml``, il ne pourra référencer que les URL commençant par |
|---|
| 65 |
``/content/``. |
|---|
| 66 |
|
|---|
| 67 |
La vue sitemap nécessite un argument supplémentaire: ``{'sitemaps': sitemaps}``. |
|---|
| 68 |
`` sitemaps`` doit être un dictionnaire qui établit la correspondance entre |
|---|
| 69 |
la description courte d'une section (par exemple, ``blog`` ou bien ``news``) et sa classe |
|---|
| 70 |
``Sitemap`` (par exemple, ``BlogSitemap`` ou ``NewsSitemap``). Il peut aussi mettre |
|---|
| 71 |
en relation la description avec une *instance* de la classe ``Sitemap`` |
|---|
| 72 |
(e.g., ``BlogSitemap(une_var)``). |
|---|
| 73 |
|
|---|
| 74 |
.. _URLconf: ../url_dispatch/ |
|---|
| 75 |
|
|---|
| 76 |
La classe Sitemap |
|---|
| 77 |
================= |
|---|
| 78 |
|
|---|
| 79 |
Une classe ``Sitemap`` est simplement une classe Python représentant une "section" |
|---|
| 80 |
d'entrées dans votre plan de site. Par exemple, une classe ``Sitemap`` peut |
|---|
| 81 |
représenter toutes les entrées de votre blog, tandis qu'une autre peut |
|---|
| 82 |
représenter tous les événements de votre agenda. |
|---|
| 83 |
|
|---|
| 84 |
Dans le cas le plus simple, toutes ces sections sont regroupées dans |
|---|
| 85 |
un fichier ``sitemap.xml``, mais il est également possible d'utiliser le |
|---|
| 86 |
framework pour générer un index de plan de site qui référence des fichiers de plan de site |
|---|
| 87 |
individuels, un par section. (Voir `Création d'un index de plan de site`_ plus bas.) |
|---|
| 88 |
|
|---|
| 89 |
Les classes ``Sitemap`` doivent dériver de ``django.contrib.sitemaps.Sitemap``. |
|---|
| 90 |
Elle peuvent apparaître n'importe où dans votre code. |
|---|
| 91 |
|
|---|
| 92 |
Exemple simple |
|---|
| 93 |
============== |
|---|
| 94 |
|
|---|
| 95 |
Considérons que vous avez un systÚme de blog, avec un modÚle ``Entry``, et que |
|---|
| 96 |
vous vouliez que votre plan de site comprenne tous les liens vers les entrées |
|---|
| 97 |
de votre blog. Voila à quoi pourrait ressembler votre classe sitemap:: |
|---|
| 98 |
|
|---|
| 99 |
from django.contrib.sitemaps import Sitemap |
|---|
| 100 |
from mysite.blog.models import Entry |
|---|
| 101 |
|
|---|
| 102 |
class BlogSitemap(Sitemap): |
|---|
| 103 |
changefreq = "never" |
|---|
| 104 |
priority = 0.5 |
|---|
| 105 |
|
|---|
| 106 |
def items(self): |
|---|
| 107 |
return Entry.objects.filter(is_draft=False) |
|---|
| 108 |
|
|---|
| 109 |
def lastmod(self, obj): |
|---|
| 110 |
return obj.pub_date |
|---|
| 111 |
|
|---|
| 112 |
Note: |
|---|
| 113 |
|
|---|
| 114 |
* ``changefreq`` et ``priority`` sont des attributs de classe correspondant, |
|---|
| 115 |
respectivement, aux éléments ``<changefreq>`` et ``<priority>``. On |
|---|
| 116 |
peut les rendre invocables en tant que fonctions, comme ``lastmod`` dans l'exemple. |
|---|
| 117 |
* ``items()`` est simplement une méthode pour obtenir en retour une liste d'objets. Les |
|---|
| 118 |
objets de cette liste seront transférés aux méthodes invocables qui correspondraient à |
|---|
| 119 |
une propriété (``location``, ``lastmod``, ``changefreq``, and ``priority``). |
|---|
| 120 |
* Avec ``lastmod`` on obtient en retour un objet Python de type ``datetime``. |
|---|
| 121 |
* Dans cet exemple, il n'y a pas de méthode ``location``, mais vous pouvez |
|---|
| 122 |
la mettre afin de spécifier l'URL de votre objet. Par défaut, ``location()`` |
|---|
| 123 |
appelle ``get_absolute_url()`` sur chaque objet et donne en retour le résultat. |
|---|
| 124 |
|
|---|
| 125 |
|
|---|
| 126 |
Référence de la classe Sitemap |
|---|
| 127 |
============================== |
|---|
| 128 |
|
|---|
| 129 |
Une classe ``Sitemap`` peut définir les méthodes/attributs suivants: |
|---|
| 130 |
|
|---|
| 131 |
``items`` |
|---|
| 132 |
--------- |
|---|
| 133 |
|
|---|
| 134 |
**Obligatoire.** Méthode qui permet de donner en retour une liste d'objets. Le framework ne |
|---|
| 135 |
se préoccupe pas du *type* des objets, l'important étant que ces objets puissent |
|---|
| 136 |
être utilisés comme argument pour les méthodes ``location()``, ``lastmod()``, |
|---|
| 137 |
``changefreq()`` et ``priority()``. |
|---|
| 138 |
|
|---|
| 139 |
``location`` |
|---|
| 140 |
------------ |
|---|
| 141 |
|
|---|
| 142 |
**Optionnel.** Méthode ou bien attribut. |
|---|
| 143 |
|
|---|
| 144 |
S'il s'agit d'une méthode, elle doit donner en retour l'URL absolue pour un |
|---|
| 145 |
objet donné renvoyé par ``items()``. |
|---|
| 146 |
|
|---|
| 147 |
S'il s'agit d'un attribut, sa valeur doit être une chaîne de caractÚres |
|---|
| 148 |
représentant une URL absolue à utiliser pour chaque objet renvoyé par ``items()``. |
|---|
| 149 |
|
|---|
| 150 |
Dans les deux cas, "URL absolue" signifie une URL ne contenant pas le protocole |
|---|
| 151 |
ou le domaine. Exemples: |
|---|
| 152 |
|
|---|
| 153 |
* bon: ``'/foo/bar/'`` |
|---|
| 154 |
* mauvais: ``'example.com/foo/bar/'`` |
|---|
| 155 |
* mauvais: ``'http://example.com/foo/bar/'`` |
|---|
| 156 |
|
|---|
| 157 |
Si ``location`` n'est pas présent, le framework appelera la |
|---|
| 158 |
méthode ``get_absolute_url()`` sur chaque objet renvoyé par ``items()``. |
|---|
| 159 |
|
|---|
| 160 |
|
|---|
| 161 |
``lastmod`` |
|---|
| 162 |
----------- |
|---|
| 163 |
|
|---|
| 164 |
**Optionnel.** Méthode ou bien attribut. |
|---|
| 165 |
|
|---|
| 166 |
S'il s'agit d'une méthode, elle doit accepter un argument -- un objet |
|---|
| 167 |
renvoyé par ``items()`` -- et indiquer en retour la date de la derniÚre modification |
|---|
| 168 |
de cet objet, sous la forme d'un objet Python ``datetime.datetime``. |
|---|
| 169 |
|
|---|
| 170 |
S'il s'agit d'un attribut, sa valeur doit être un objet Python ``datetime.datetime`` |
|---|
| 171 |
représentant la derniÚre date de modification pour *chaque* objet renvoyé |
|---|
| 172 |
par ``items()``. |
|---|
| 173 |
|
|---|
| 174 |
``changefreq`` |
|---|
| 175 |
-------------- |
|---|
| 176 |
|
|---|
| 177 |
**Optionnel.** Méthode ou bien attribut. |
|---|
| 178 |
|
|---|
| 179 |
S'il s'agit d'une méthode, elle doit accepter un argument -- un objet |
|---|
| 180 |
renvoyé par ``items()`` -- et indiquer en retour la fréquence de modification de |
|---|
| 181 |
cet objet, sous la forme d'une chaîne de caractÚres. |
|---|
| 182 |
|
|---|
| 183 |
S'il s'agit d'un attribut, sa valeur doit être une chaîne de caractÚres |
|---|
| 184 |
représentant la fréquence de modification pour *chaque* objet renvoyé |
|---|
| 185 |
par ``items()``. |
|---|
| 186 |
|
|---|
| 187 |
Les valeurs possibles pour ``changefreq``, que ce soit une méthode ou un attribut, sont: |
|---|
| 188 |
|
|---|
| 189 |
* ``'always'`` : en permanence |
|---|
| 190 |
* ``'hourly'`` : toutes les heures |
|---|
| 191 |
* ``'daily'`` : quotidiennement |
|---|
| 192 |
* ``'weekly'`` : chaque semaine |
|---|
| 193 |
* ``'monthly'`` : mensuellement |
|---|
| 194 |
* ``'yearly'`` : annuellement |
|---|
| 195 |
* ``'never'`` : jamais |
|---|
| 196 |
|
|---|
| 197 |
``priority`` |
|---|
| 198 |
------------ |
|---|
| 199 |
|
|---|
| 200 |
**Optionnel.** Méthode ou bien attribut. |
|---|
| 201 |
|
|---|
| 202 |
S'il s'agit d'une méthode, elle doit accepter un argument -- un objet |
|---|
| 203 |
renvoyé par ``items()`` -- et indiquer en retour la priorité de l'objet, sous la |
|---|
| 204 |
forme soit d'un flottant soit d'une chaîne de caractÚres. |
|---|
| 205 |
|
|---|
| 206 |
S'il s'agit d'un attribut, sa valeur doit être soit une chaîne de caractÚres |
|---|
| 207 |
soit un flottant représentant la priorité pour *chaque* objet renvoyé |
|---|
| 208 |
par ``items()``. |
|---|
| 209 |
|
|---|
| 210 |
Exemple de valeurs pour ``priority``: ``0.4``, ``1.0``. Par défaut, la priorité |
|---|
| 211 |
d'une page est ``0.5``. Voir la `documentation sitemaps.org`_ pour plus d'informations. |
|---|
| 212 |
|
|---|
| 213 |
|
|---|
| 214 |
.. _documentation sitemaps.org: http://www.sitemaps.org/protocol.html#prioritydef |
|---|
| 215 |
|
|---|
| 216 |
Raccourcis |
|---|
| 217 |
========== |
|---|
| 218 |
|
|---|
| 219 |
Le framework sitemap fournit, dans un but pratique, quelques classes |
|---|
| 220 |
pour les cas d'utilisations courants: |
|---|
| 221 |
|
|---|
| 222 |
|
|---|
| 223 |
``FlatPageSitemap`` |
|---|
| 224 |
------------------- |
|---|
| 225 |
|
|---|
| 226 |
La classe ``django.contrib.sitemaps.FlatPageSitemap`` prend en compte toutes les |
|---|
| 227 |
`pages à plat`_ définies dans le ``SITE_ID`` en question (voir la `documentation sur |
|---|
| 228 |
les sites`_) et génÚre une entrée dans le plan de site. Ces entrées contiennent |
|---|
| 229 |
uniquement l'attribut ``location`` et non ``lastmod``, ``changefreq`` ou ``priority``. |
|---|
| 230 |
|
|---|
| 231 |
.. _pages à plat: ../flatpages/ |
|---|
| 232 |
.. _documentation sur les sites: ../sites/ |
|---|
| 233 |
|
|---|
| 234 |
``GenericSitemap`` |
|---|
| 235 |
------------------ |
|---|
| 236 |
|
|---|
| 237 |
La classe ``GenericSitemap`` fonctionne avec n'importe quelle `vue générique`_ déjà présente. |
|---|
| 238 |
Pour l'utiliser, créez une instance, en passant en paramÚtre le même ``info_dict`` |
|---|
| 239 |
utilisé pour la vue générique. La seule contrainte est d'avoir une entrée ``queryset`` |
|---|
| 240 |
dans le dictionnaire. Ce dernier peut aussi contenir une entrée ``date_field`` afin de spécifier |
|---|
| 241 |
un champ de date pour les objets récupérés dans le ``queryset``. Ce champ sera alors utilisé |
|---|
| 242 |
pour l'attribut ``lastmod`` dans le plan de site généré. On peut aussi |
|---|
| 243 |
passer les arguments mot-clé ``priority`` et ``changefreq`` au constructeur |
|---|
| 244 |
de ``GenericSitemap`` pour spécifier ces attributs dans toutes les URL. |
|---|
| 245 |
|
|---|
| 246 |
.. _vue générique: ../generic_views/ |
|---|
| 247 |
|
|---|
| 248 |
Exemple |
|---|
| 249 |
------- |
|---|
| 250 |
|
|---|
| 251 |
Voici un exemple d'un fichier URLConf_ utilisant les deux raccourcis:: |
|---|
| 252 |
|
|---|
| 253 |
from django.conf.urls.defaults import * |
|---|
| 254 |
from django.contrib.sitemaps import FlatPageSitemap, GenericSitemap |
|---|
| 255 |
from mysite.blog.models import Entry |
|---|
| 256 |
|
|---|
| 257 |
info_dict = { |
|---|
| 258 |
'queryset': Entry.objects.all(), |
|---|
| 259 |
'date_field': 'pub_date', |
|---|
| 260 |
} |
|---|
| 261 |
|
|---|
| 262 |
sitemaps = { |
|---|
| 263 |
'flatpages': FlatPageSitemap, |
|---|
| 264 |
'blog': GenericSitemap(info_dict, priority=0.6), |
|---|
| 265 |
} |
|---|
| 266 |
|
|---|
| 267 |
urlpatterns = patterns('', |
|---|
| 268 |
# some generic view using info_dict |
|---|
| 269 |
# ... |
|---|
| 270 |
|
|---|
| 271 |
# the sitemap |
|---|
| 272 |
(r'^sitemap.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps}) |
|---|
| 273 |
) |
|---|
| 274 |
|
|---|
| 275 |
.. _URLconf: ../url_dispatch/ |
|---|
| 276 |
|
|---|
| 277 |
Création d'un index de plan de site |
|---|
| 278 |
=================================== |
|---|
| 279 |
|
|---|
| 280 |
Le framework sitemap permet aussi de créer un index de plan de site |
|---|
| 281 |
qui référence des fichiers de plan de site individuels, un pour chaque |
|---|
| 282 |
section définie dans votre dictionnaire ``sitemaps``. Les seules |
|---|
| 283 |
différences dans la pratique sont: |
|---|
| 284 |
|
|---|
| 285 |
* Vous utilisez deux vues dans votre URLconf : ``django.contrib.sitemaps.views.index`` |
|---|
| 286 |
et ``django.contrib.sitemaps.views.sitemap``. |
|---|
| 287 |
* La vue ``django.contrib.sitemaps.views.sitemap`` doit accepter un |
|---|
| 288 |
argument mot-clé ``section``. |
|---|
| 289 |
|
|---|
| 290 |
Voici à quoi devraient ressembler les lignes correspondantes de URLconf pour l'exemple ci-dessus:: |
|---|
| 291 |
|
|---|
| 292 |
(r'^sitemap.xml$', 'django.contrib.sitemaps.views.index', {'sitemaps': sitemaps}) |
|---|
| 293 |
(r'^sitemap-(?P<section>.+).xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps}) |
|---|
| 294 |
|
|---|
| 295 |
Cela générera automatiquement un fichier ``sitemap.xml`` qui référencera |
|---|
| 296 |
à la fois ``sitemap-flatpages.xml`` et ``sitemap-blog.xml``. La classe |
|---|
| 297 |
``Sitemap`` et le dictionnaire ``sitemaps`` ne sont pas modifiés. |
|---|
| 298 |
|
|---|
| 299 |
Faire un "ping" sur Google |
|---|
| 300 |
========================== |
|---|
| 301 |
|
|---|
| 302 |
Vous aurez peut-être envie de faire un "ping" sur Google lors d'une modification de |
|---|
| 303 |
votre plan de site, afin qu'il réindexe votre site. Le framework fournit |
|---|
| 304 |
une fonction pour cela: ``django.contrib.sitemaps.ping_google()``. |
|---|
| 305 |
|
|---|
| 306 |
``ping_google()`` accepte un argument optionnel, ``sitemap_url``, qui doit être |
|---|
| 307 |
l'URL absolue de votre plan de site (par exemple, ``'/sitemap.xml'``). Si cet argument |
|---|
| 308 |
n'est pas fourni, ``ping_google()`` essaiera de retrouver votre plan de site |
|---|
| 309 |
en effectuant une recherche inversée à partir de votre URLconf. |
|---|
| 310 |
|
|---|
| 311 |
``ping_google()`` lÚve l'exception |
|---|
| 312 |
``django.contrib.sitemaps.SitemapNotFound`` s'il ne peut pas déterminer l'URL |
|---|
| 313 |
de votre plan de site. |
|---|
| 314 |
|
|---|
| 315 |
Une maniÚre pratique d'appeler ``ping_google()`` est de le faire à partir |
|---|
| 316 |
de la méthode ``save()`` d'un modÚle:: |
|---|
| 317 |
|
|---|
| 318 |
from django.contrib.sitemaps import ping_google |
|---|
| 319 |
|
|---|
| 320 |
class Entry(models.Model): |
|---|
| 321 |
# ... |
|---|
| 322 |
def save(self): |
|---|
| 323 |
super(Entry, self).save() |
|---|
| 324 |
try: |
|---|
| 325 |
ping_google() |
|---|
| 326 |
except Exception: |
|---|
| 327 |
# Bare 'except' because we could get a variety |
|---|
| 328 |
# of HTTP-related exceptions. |
|---|
| 329 |
pass |
|---|
| 330 |
|
|---|
| 331 |
Toutefois, une solution plus efficace serait d'appeler ``ping_google()`` |
|---|
| 332 |
à partir d'un script cron, ou tout autre gestionnaire de tâche. Cette fonction |
|---|
| 333 |
envoie une requête HTTP vers les serveurs de Google, donc peut-être faudra-t-il |
|---|
| 334 |
éviter d'ajouter cette surcharge au réseau à chaque fois que vous appelez ``save()``. |
|---|