Crear un Mapa de Sitio (SiteMap.xml) en Django

El sitemap de nuestra aplicación es muy sencillo, pero antes de implementarlo, quiero que entres en contexto y entiendas por qué estamos haciendo todo esto.

El sitemap es, básicamente, un archivo que contiene una lista de las URLs de nuestro sitio. Aquí tengo un par de publicaciones, por eso se ven solo dos. En la parte superior aparece el dominio principal pero eso ya depende de ti. Lo importante está en el contenido del archivo, no tanto en el dominio.

¿Qué es un sitemap?

En caso de que no lo conozcas, el sitemap es un archivo (por lo general, un XML) que le indica a los motores de búsqueda —como Google— qué páginas contiene tu sitio. Esto les permite navegar tu contenido sin tener que rastrear todo el HTML, accediendo directamente a las URLs listadas.

<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
  <url>
    <loc>https://www.desarrollolibre.net</loc>
  </url>
</urlset>

Usualmente, se colocan en este archivo solo las URLs que queremos indexar, como las publicaciones o páginas relevantes. Las páginas de listados normalmente no se incluyen, ya que no aportan tanto desde el punto de vista del SEO.

Estructura del sitemap (XML)

El sitemap es simplemente un archivo XML con una estructura específica. Estas son las etiquetas que se emplean. Puedes agregar más opciones, como:

  1. Frecuencia de actualización.
  2. Fecha de expiración.
  3. Prioridad.

Generalmente, el sitemap debería estar en la raíz del sitio (/sitemap.xml). Sin embargo, en este ejercicio lo coloqué dentro de la aplicación llamada blog, ya que así tengo estructurado el proyecto.

Hay documentación muy buena sobre esto, como la de Mozilla, que te puede ayudar si deseas profundizar más.

En este ejercicio estoy usando la versión más sencilla del XML porque no quiero complicar demasiado el ejemplo.

Si quisieras moverlo, tendrías que modificar las URLs en las que lo estás generando. En mi caso no me molesta que esté en una subruta, ya que de igual manera lo declaramos en el archivo robots.txt, indicando dónde está ubicado el sitemap.

Implementación del sitemap en Django

Ahora sí, veamos cómo se implementa.

1. Generar la URL de cada publicación

Un reto que tuvimos fue que Django no nos proporciona directamente el BASE_URL. Al menos, no de forma sencilla. Así que lo generamos nosotros manualmente y lo usamos para componer cada URL del sitemap:

class PostSitemap(ListView):
    model = Post
    context_object_name = 'posts'
    template_name = 'post/sitemap.html'

    def render_to_response(self, context, **response_kwargs):
        response_kwargs['content_type'] = 'application/xml'
        context['base_url'] = self.request.build_absolute_uri('/').rstrip('/')
        return super().render_to_response(context, **response_kwargs)

En el modelo Post, declaré un método llamado get_url (o algo similar, como getRoute). Este método genera la URL en base al nombre de la ruta y al slug del post. Django Templates tienen ciertas limitaciones para generar URLs (como usar reverse), por lo que este método nos facilita mucho las cosas desde la plantilla:

class Post(models.Model):
    def getRoute(self):
        return reverse("b.show", args=[self.slug])

2. Crear la vista que devuelve el XML

Creamos una vista basada en clase muy parecida a la que usamos para los listados. La diferencia clave está en:

  • Cambiar el Content-Type de la respuesta a application/xml.
  • Pasar el base_url como parte del contexto.

Además, usamos render_to_response() para personalizar la respuesta final y agregar el contexto adicional. Un detalle técnico: eliminé el slash final del base_url porque los slugs ya lo incluyen, y no quería tener doble barra (//) en las URLs.

3. Plantilla del sitemap

La plantilla es un archivo XML donde usamos el motor de plantillas de Django. Aquí:

  • Declaramos la estructura del sitemap (<urlset> y <url>).
  • Usamos filtros como add (|add) para concatenar strings.
  • Iteramos sobre las publicaciones y generamos cada URL combinando el base_url con el método de ruta del post.

También dejé comentarios en el template para que puedas hacer pruebas o modificarlo si quieres cambiar algo.

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
    <url>
        {% comment %} <loc>{{ request.build_absolute_uri|add:"/" }}</loc> {% endcomment %}
        <loc>{{ base_url }}</loc>
    </url>
    {% for post in posts %}
    <url>
        <loc>{{ base_url|add:post.getRoute }}</loc>
    </url>
    {% endfor %}
</urlset>

Al acceder a la ruta correspondiente, verás el XML generado con las URLs de las publicaciones. Puedes verificar que el Content-Type es application/xml, lo cual es importante para que el navegador o los bots lo interpreten correctamente.

Con esto, ya tienes tu sitemap implementado en Django. Es simple, funcional y fácil de mantener. Ideal para comenzar con buenas prácticas en cuanto a SEO y estructuración del sitio.

Acepto recibir anuncios de interes sobre este Blog.

Te muestro como crear un Sitemap en una app en Django con las vistas basadas en clases.

- Andrés Cruz

In english