Un sitemap es un fichero XML en tu sitio web que le indica a los indexadores de los motores de búsqueda cuan frecuentemente cambian tus páginas así como la "importancia" relativa de ciertas páginas en relación con otras (siempre hablando de páginas de tu sitio). Esta información ayuda a los motores de búsqueda a indexar tu sitio.
Por ejemplo, esta es una parte del sitemap del sitio web de Django
que se encuentra en http://djangoproject.com/sitemap.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>http://www.djangoproject.com/documentation/</loc>
<changefreq>weekly</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>http://www.djangoproject.com/documentation/0_90/</loc>
<changefreq>never</changefreq>
<priority>0.1</priority>
</url>
...
</urlset>
Para más información sobre sitemaps, vea http://www.sitemaps.org/.
El framework sitemap de Django automatiza la creación de este fichero XML si
lo indicas expresamente en el código Python. Para crear un sitemap, debes
simplemente escribir una clase Sitemap
y hacer referencia a la misma en tu
URLconf.
11.6.1. Instalación
Para instalar la aplicación sitemap, sigue los siguientes pasos:
- Agrega
'django.contrib.sitemaps'
a tu variable de configuraciónINSTALLED_APPS
. - Asegúrate de que
'django.template.loaders.app_directories.load_template_source'
está en tu variable de configuraciónTEMPLATE_LOADERS
. Por omisión se encuentra activado, por lo que los cambios son necesarios solamente si modificaste dicha variable de configuración. - Asegúrate de que tienes instalado el framework sites (ver Capítulo 14).
Nota La aplicación sitemap no instala tablas en la base de datos. La única razón
de que esté en INSTALLED_APPS
es que el cargador de plantillas
load_template_source
pueda encontrar las plantillas incluídas.
11.6.2. Inicialización
Para activar la generación del sitemap en tu sitio Django, agrega la siguiente línea a tu URLconf:
(r'^sitemap.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps})
Esta línea le dice a Django que construya un sitemap cuando un cliente accede
a /sitemap.xml
.
El nombre del fichero sitemap no es importante, pero la ubicación sí lo es. Los
motores de búsqueda solamente indexan los enlaces en tu sitemap para el nivel
de URL actual y anterior. Por ejemplo, si sitemap.xml
reside en tu directorio
principal, el mismo puede hacer referencia a cualquier URL en tu sitio. Pero si
tu sitemap reside en /content/sitemap.xml
, solamente podrá hacer referencia
a URLs que comiencen con /content/
.
La vista sitemap toma un argumento extra: {'sitemaps': sitemaps}
.
sitemaps
debe ser un diccionario que mapee una etiqueta corta de sección (p.
ej. blog
o news
) a tu clase Sitemap
(p.e., BlogSitemap
o
NewsSitemap
). También mapea hacia una instancia de una clase Sitemap
(p. ej. BlogSitemap(some_var)
).
11.6.3. Clases Sitemap
Una clase Sitemap
es simplemente una clase Python que representa una
"sección" de entradas en tu sitemap. Por ejemplo, una clase Sitemap
puede
representar todas las entradas de tu weblog, y otra puede representar todos los
eventos de tu calendario.
En el caso más simple, todas estas secciones se unen en un único sitemap.xml
,
pero también es posible usar el framework para generar un índice sitemap que
haga a referencia ficheros sitemap individuales, uno por sección (
describiéndolo sintéticamente).
Las clases Sitemap
debe ser una subclase de
django.contrib.sitemaps.Sitemap
. Estas pueden residir en cualquier parte del
árbol de código.
Por ejemplo, asumamos que posees un sistema de blog, con un modelo Entry
, y
quieres que tu sitemap incluya todos los enlaces a las entradas individuales
de tu Blog. Tu clase Sitemap
debería verse así:
from django.contrib.sitemaps import Sitemap
from mysite.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
Declarar un Sitemap
debería verse muy similar a declarar un Feed
; esto
es justamente un objetivo del diseño.
En manera similar a las clases Feed
, los miembros de Sitemap
pueden ser
métodos o atributos. Ver los pasos en la sección "Un feed más complejo" para
más información sobre cómo funciona esto.
Una clase Sitemap
puede definir los siguientes métodos/atributos:
items
(requerido): Provee una lista de objetos. Al framework no le importa que tipo de objeto es; todo lo que importa es que los objetos sean pasados a los métodoslocation()
,lastmod()
,changefreq()
, ypriority()
.location
(opcional): Provee la URL absoluta para el objeto dado. Aquí "URL absoluta" significa una URL que no incluye el protocolo o el dominio. Estos son algunos ejemplos:- Bien:
'/foo/bar/'
- Mal:
'example.com/foo/bar/'
- Mal:
'http://example.com/foo/bar/'
Silocation
no es provisto, el framework llamará al métodoget_absolute_url()
en cada uno de los objetos retornados poritems()
.
- Bien:
lastmod
(opcional): La fecha de "última modificación" del objeto, como un objetodatetime
de Python.changefreq
(opcional): Cuán a menudo el objeto cambia. Los valores posibles (según indican las especificaciones de Sitemaps) son:'always'
'hourly'
'daily'
'weekly'
'monthly'
'yearly'
'never'
priority
(opcional): Prioridad sugerida de indexado entre0.0
y1.0
. La prioridad por omisión de una página es0.5
; ver la documentación de http://sitemaps.org para más información de cómo funcionapriority
.
11.6.4. Accesos directos
El framework sitemap provee un conjunto de clases para los casos más comunes. Describiremos estos casos en las secciones a continuación.
11.6.4.1. FlatPageSitemap
La clase django.contrib.sitemaps.FlatPageSitemap
apunta a todas las páginas
planas definidas para el sitio actual y crea una entrada en el sitemap. Estas
entradas incluyen solamente el atributo location
— no lastmod
,
changefreq
, o priority
.
Para más información sobre Páginas Planas ver el Capítulo 14.
11.6.4.2. Sitemap Genérico
La clase GenericSitemap
trabaja con cualquier vista genérica (ver Capítulo 9)
que hayas definido con anterioridad.
Para usarla, crea una instancia, pasándola en el mismo info_dict
que se pasa
a la vista genérica. El único requerimiento es que el diccionario tenga una
entrada queryset
. También debe poseer una entrada date_field
que
especifica un campo fecha para los objetos obtenidos del queryset
. Esto será
usado por el atributo lastmod
en el sitemap generado. También puedes pasar
los argumentos palabra clave (keyword) priority
y changefreq
al
constructor GenericSitemap
para especificar dichos atributos para todas las
URLs.
Este es un ejemplo de URLconf usando tanto, FlatPageSitemap
como
GenericSiteMap
(con el anterior objeto hipotético Entry
):
from django.conf.urls.defaults import *
from django.contrib.sitemaps import FlatPageSitemap, GenericSitemap
from mysite.blog.models import Entry
info_dict = {
'queryset': Entry.objects.all(),
'date_field': 'pub_date',
}
sitemaps = {
'flatpages': FlatPageSitemap,
'blog': GenericSitemap(info_dict, priority=0.6),
}
urlpatterns = patterns('',
# some generic view using info_dict
# ...
# the sitemap
(r'^sitemap.xml$',
'django.contrib.sitemaps.views.sitemap',
{'sitemaps': sitemaps})
)
11.6.5. Crear un índice Sitemap
El framework sitemap también tiene la habilidad de crear índices sitemap que
hagan referencia a ficheros sitemap individuales, uno por cada sección definida
en tu diccionario sitemaps
. Las única diferencias de uso son:
- Usas dos vistas en tu URLconf:
django.contrib.sitemaps.views.index
ydjango.contrib.sitemaps.views.sitemap
. - La vista
django.contrib.sitemaps.views.sitemap
debe tomar un parámetro que corresponde a una palabra clave, llamadosection
.
Así deberían verse las líneas relevantes en tu URLconf para el ejemplo anterior:
(r'^sitemap.xml$',
'django.contrib.sitemaps.views.index',
{'sitemaps': sitemaps}),
(r'^sitemap-(?P<section>.+).xml$',
'django.contrib.sitemaps.views.sitemap',
{'sitemaps': sitemaps})
Esto genera automáticamente un fichero sitemap.xml
que hace referencia a
ambos ficheros sitemap-flatpages.xml
y sitemap-blog.xml
. La clase
Sitemap
y el diccionario sitemaps
no cambian en absoluto.
11.6.6. Hacer ping a Google
Puedes desear hacer un "ping" a Google cuando tu sitemap cambia, para hacerle
saber que debe reindexar tu sitio. El framework provee una función para hacer
justamente eso: django.contrib.sitemaps.ping_google()
.
Nota Hasta el momento en que este libro se escribió, únicamente Google responde a los pings de sitemap. Pero es muy probable que pronto Yahoo y/o MSN también admitan estos pings.
Cuando eso suceda, cambiaremos el nombre de ping_google()
a algo como
ping_search_engines()
, así que asegúrate de verificar la ultima
documentación sobre sitemap.
ping_google()
toma un argumento opcional, sitemap_url
, que debe ser la
URL absoluta de tu sitemap (por ej., '/sitemap.xml'
). Si este argumento no es
provisto, ping_google()
tratará de generar un sitemap realizando una
búsqueda reversa en tu URLconf.
ping_google()
lanza la excepción
django.contrib.sitemaps.SitemapNotFound
si no puede determinar la URL de tu
sitemap.
Una forma útil de llamar a ping_google()
es desde el método save()
:
from django.contrib.sitemaps import ping_google
class Entry(models.Model):
# ...
def save(self):
super(Entry, self).save()
try:
ping_google()
except Exception:
# Bare 'except' because we could get a variety
# of HTTP-related exceptions.
pass
Una solución más eficiente, sin embargo, sería llamar a ping_google()
desde
un script cron
o un manejador de tareas. La función hace un pedido HTTP a
los servidores de Google, por lo que no querrás introducir esa demora asociada
a la actividad de red cada vez que se llame al método save()
.