O framework sitemap

Django comes with a high-level sitemap-generating framework that makes creating sitemap XML files easy.

O Django vem com um framework de alto-nível gerador de sitemaps que torna a criação de um sitemap em XML fácil.

Visão geral

Um sitemap é um arquivo XML sobre o seu site Web que diz aos indexadores dos motores de busca, frequentemente, como suas páginas mudam e quão “importante” é certas páginas em relação a outras. Esta informação ajuda o buscadores a indexar seu site.

O framework sitemap do Django automatiza a criação destes arquivos XML deixando vocês expressar esta informação em código Python.

Ele funciona parecido com o frameworkd syndcation. Para criar um sitemap, é só escrever uma classe Sitemap e criar uma URl no seu URLconf.

Instalação

Para instalar a aplicação sitemap, siga estes passos:

  1. Adicione 'django.contrib.sitemaps' ao seu INSTALLED_APPS.
  2. Esteja certo de que tenha o 'django.template.loaders.app_directories.load_template_source' no seu TEMPLATE_LOADERS. Ele é setado por padrão, assim você só precisa mudar isso se você tiver alterado essa configuração.
  3. Assegure-se de ter instalado o framework sites.

(Nota: A aplicação sitemap naõ instala qualquer tabela no banco de dados. A única razão dela precisar estar no INSTALLED_APPS é para o template loader load_template_source() poder encontrar os templates padrões.)

Inicialização

Para ativar a geração do sitemap no seu site Django, adicion esta linha ao seu URLconf:

(r'^sitemap.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps})

Isto diz ao Django para fazer o sitemap quando um cliente acessa /sitemap.xml.

O nome do arquivo do sitemap não é importanto, mas a localização é. O buscadores somente indexam links no seu sitemap para o nível atual e inferiores. Por instância, se sitemap.xml reside no seu diretório root, ele poderá referenciar qualquer URL no seu site. Entretanto, se seu sitemap fica em /content/sitemap.xml, ele somente referencia as URLs apartir de /content/.

O view sitemap recebe um argumento extra, e obrigatório: {'sitemaps': sitemaps}. O sitemaps deve ser um dicionário que mapea um label curto da seção (e.g, blog ou news) para sua classe Sitemap (e.g, BlogSitemap ou NewsSitemap). Ele pode também mapear para uma instância da classe Sitemap (e.g., BlogSitemap(some_var)).

Classes do sitemap

Uma classe Sitemap é uma simples classe Python que representa uma “seção” de entradas no sitemap. Por exemplo, uma classe Sitemap representaria todoas as entradas do seu weblog, enquando outra representaria todos os eventos do seu calendário de eventos.

Num caso simplista, todas essas seções seriam agrupadas num arquivo sitemap.xml, mas somente é possível usar o framework para gerar um sitemap index que representa arquivos individuais, um por seção. (Veja, Criando um sitemap index abaixo.)

As classes Sitemap devem extender django.contrib.sitemaps.Sitemap. Elas podem estar em qualquer lugar de sua base de código.

Um exemplo simples

Vamos assumir que você tem um sistema de blog, com um model Entry, e você deseja que seu sitemap inclua todos os links de suas entradas de no blog. Aqui tem como sua classe sitemap pode parecer:

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

Note:

  • changefreq e priority são atributos de classes correspondentes aos elementos <changefreq> e <priority>, respectivamente. Eles podem ser chamados como funções, como o lastmod foi no último exemplo.
  • items() é simplesmente um métod que retorna uma lista de objetos. Os objetos retornados serão passados para qualquer método chamável correspondendo a uma propriedade do sitemap (location, lastmod, changefreq, e priority).
  • lastmod deve retornar um objeto Python datetime.
  • Não há o método location neste exemplo, mas você pode fornecê-la a fim de especificar a URL para o objeto. Por padrão, location() chama o método get_absolute_url() de cada objeto e retorna o resultado.

Referência da classe Sitemap

class Sitemap

Uma classe Sitemap pode definir os seguintes métodos/atributos:

items

Obrigatório. Um método que retorna uma lista de objetos. O framework não se preocupa com o tipo de objetos que eles são; tudo que importa é que estes objetos são passados para os métodos location(), lastmod(), changefreq() e priority().

location

Opicional. Ambos método ou atributo.

Se ele for um método, ele deve retornar a URL absoluta para um dado objeto como retornado pelo items().

Se ele for um atributo, seu valor deve ser uma string representando uma URL absoluta para ser usada por todos os objetos retornados pelo items().

Em ambos os casos, a “URL absoluta” significa uma URL que não inclui o

protocolo ou domínio. Exemplos:

  • Bom: '/foo/bar/'
  • Ruim: 'example.com/foo/bar/'
  • Ruim: 'http://example.com/foo/bar/'

Se o location não é fornecido, o framework chamará o método get_absolute_url() de cada objeto retornado pelo items().

lastmod

Opcional. Ambos, método ou atributo.

Se for um método, deve receber um argumento – um objeto retornado pelo items() – e retornar a data/hora da última modificação deste objeto, como um objeto Python datetime.datetime.

Se for um atributo, seu valor deve ser um objeto Python datetime.datetime representando a data/hora da última modificação para todo objeto retornado por items().

changefreq

Opcional. Ambos, método ou atributo.

Se for um método, ele deve receber um argumento – um objeto retornado por items() – e retornar a frequencia de mudança deste objeto, como uma string Python.

Se for um atributo, seu valor deve ser uma string representando a frequência de mudança para todo objeto retornado por items().

Os valores possíveis para changefreq, se você você usar um método ou atributo, são:

  • 'always'
  • 'hourly'
  • 'daily'
  • 'weekly'
  • 'monthly'
  • 'yearly'
  • 'never'
priority()

Opcional. Ambos, método ou atributo.

Se for um método, deve ser receber um argumento – um objeto retornado por items() – e retorna a prioridade deste objeto, como uma string ou float.

Se for um atributo, seu valor deve ser ou uma string ou uma float representando a prioridade de todo objeto retornado por items().

Exemplo de valores para :attr`~Sitemap.priority`: 0.4, 1.0. O valor de prioridade padrão de uma página é 0.5. Veja a documentação do sitemaps.org para saber mais.

Shortcuts

O framework sitemap fornece algumas classes convenientes para casos comuns:

class FlatPageSitemap

A classe django.contrib.sitemaps.FlatPageSitemap se parece com a flatpages definida para o SITE_ID atual (Veja a documentação do sites) e cria uma entrada no sitemap. Estas entradas incluí somente o atributo location – não lastmod, changefreq ou priority.

class GenericSitemap

A classe django.contrib.sitemaps.GenericSitemap funciona como qualquer generic views que você já tenha. Para usá-la, cria uma instância, passando o mesmo info_dict que você passa para uma generic view. O único requesito é que o dicionário tenha uma queryset de entradas. Ele pode também ter uma entrada date_field que especifica um campo de data para objetos recebidos de um queryset. Ese será usado para o atributo lastmod no sitemap gerado. Você pode também passar os argumentos nomeados priority e changefreq para o construtor do GenericSitemap para especificar estes atributos para todas as URLs.

Exemplo

Aqui tem um exemplo de um URLconf usando ambos:

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('',
    # Algum generic view usando info_dict
    # ...

    # o sitemap
    (r'^sitemap.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps})
)

Criando um sitemap index

O framework sitemap também tem a abilidade de criar um sitemap index que referencia arquivos de sitemap individuais, um para cada seção definida no seu dicionário sitemaps. As únicas diferenças no uso são:

  • você usa dois views no seu URLconf: django.contrib.sitemaps.views.index() e django.contrib.sitemaps.views.sitemap().
  • O view django.contrib.sitemaps.views.sitemap() deve receber um argumento nomeado section.

Aqui tem como linhas relevantes do URLconf poderiam parecer para o exemplo acima:

(r'^sitemap.xml$', 'django.contrib.sitemaps.views.index', {'sitemaps': sitemaps}),
(r'^sitemap-(?P<section>.+)\.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps}),

Isto gerará automaticamente um arquivo sitemap.xml que referencia ambos sitemap-flatpages.xml e sitemap-blog.xml. As classes Sitemap e o dicionário sitemaps não mudam.

Você deve criar um arquivo index se um de seus sitemaps tem mais de 50,000 URls. Neste caso, o Django automaticamente paginará o sitemap, e o index irá reletir isso.

Pingando o Google

Você deve desejar “pingar” o Google quando seu site mudar, para permitir que ele sáiba que tem que reindexar seu site. O framework sitemaps provê uma função só para fazer isso: django.contrib.sitemaps.ping_google().

ping_google()

A função ping_google() recebe um argumento, sitemap_url, que deve ser uma URL absoluta do sitemap do seu site. (e.g., '/sitemap.xml'). Se este argumento não for fornecido, o ping_google() tentará adivinhar seu sitemap, executando uma engenharia reversa sobre seu URLconf.

O ping_google() lança uma exceção django.contrib.sitemaps.SitemapNotFound se ele não conseguir determinar a URL do sitemap.

Register with Google first!

O comando ping_google() somente funciona se você tiver registrado seu site com o Google Webmaster Tools.

Uma forma usual para chamar ping_google() é de um método save() de um model:

from django.contrib.sitemaps import ping_google

 class Entry(models.Model):
     # ...
     def save(self, force_insert=False, force_update=False):
         super(Entry, self).save(force_insert, force_update)
         try:
             ping_google()
         except Exception:
             # 'Exceção' vazia, pois nós podemos receber uma variedade de
             # exceções relacionadas ao HTTP.
             pass

Uma solução mais eficiente, entretanto, seria chamar ping_google() de um script cron, ou alguma outra tarefa agendada. A função faz uma requisição HTTP, para os servidores do Google, então você precisaria introduzir uma sobrecarga de transferência de dados para toda chamada do save().

Pingando o Google via manage.py

Uma vez que a aplicação sitemap esteja adicionada ao seu projeto, você pode também pingar os servidores do Google através da interface de linha de comando manage.py:

python manage.py ping_google [/sitemap.xml]