O framework syndication feed¶
O Django vem com um framework de alto nível para geração de feeds que criam feeds em RSS e Atom facilmente.
Para criar qualquer feed, tudo que você tem de fazer é escrever uma pequena classe Python. Você pode criar quantos feeds você quiser.
O Django também vem com uma API de baixo nível para geração de feeds. Use-a se você deseja gerar feeds fora do contexto Web, ou de alguma outra forma de mais baixo nível.
O framework de alto nível¶
Visão geral¶
O framework de alto nível é um view vinculada a URL /feeds/
por padrão. O
Django usa o restante da URL (tudo que vier depois de /feeds/
) para
determinar qual feed mostrar.
Para criar um feed, é só escrever uma classe
Feed
e apontá-la para seu
URLconf.
Inicialização¶
Para ativar os feeds no seu site Django, adicione esta linha ao seu URLconf:
(r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed', {'feed_dict': feeds}),
Isso diz ao Django para usar o framework RSS para manipular todas as URLs que
começam com "feeds/"
. (Você pode mudar o prefixo "feeds/"
para
fechar com suas próprias necessidades.)
Esta linha do URLconf tem um argumento extra: {'feed_dict': feeds}
. Use este
argumento extra para passar ao framework os feeds que devem ser publicados sob
aquela URL.
Especificamente, feed_dict
deve ser um dicionário que mapeia um slug de
um feed (uma label curta da URL) para sua classe
Feed
.
Você pode definir o feed_dict
no próprio URLconf. Aqui temos um exemplo
completo do URLconf:
from django.conf.urls.defaults import *
from myproject.feeds import LatestEntries, LatestEntriesByCategory
feeds = {
'latest': LatestEntries,
'categories': LatestEntriesByCategory,
}
urlpatterns = patterns('',
# ...
(r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed',
{'feed_dict': feeds}),
# ...
)
O exemplo acima registra dois feeds:
- O feed representado pelo
LatestEntries
ficará emfeeds/latest/
. - O feed representado pelo
LatestEntriesByCategory
ficará emfeeds/categories/
.
Uma vez configurado, você só precisa definir as classes
Feed
elas mesmas.
Classes Feed¶
Uma classe Feed
é uma simples classe
Python que representa um feed. Um feed pode ser uma simples (e.g., um feed de
“notícias do site”, ou um feed básico mostrando as últimas entradas de um blog)
ou algo mais complexo (e.g., um feed mostrando todas as entradas do blog numa
categoria particular, onde a categoria é variável).
As classes Feed
devem extender
django.contrib.syndication.feeds.Feed
. Elas podem estar em qualquer parte
de sua base de código.
Um exemplo simples¶
Este exemplo simples, extraído do chicagocrime.org, descreve um feed dos últimos cinco ítens mais novos:
from django.contrib.syndication.feeds import Feed
from chicagocrime.models import NewsItem
class LatestEntries(Feed):
title = "Chicagocrime.org site news"
link = "/sitenews/"
description = "Updates on changes and additions to chicagocrime.org."
def items(self):
return NewsItem.objects.order_by('-pub_date')[:5]
Note:
- A classe extende
django.contrib.syndication.feeds.Feed
. title
,link
edescription
correspondem aos elementos padrão do RSS<title>
,<link>
e<description>
, repectivamente.- O
items()
é, simplesmente, um métod que retorna a lista de objetos que deveriam ser incluídos no feed como elementos<item>
. Embora este exemplo retorne objetosNewsItem
usando o mapeador objeto-relacional do Django, oitems()
não tem como retornar instâncias de model. Apesar de você ter algumas funcionalidades “for free” usando os models do Django, oitems()
pode retornar qualquer tipo de objeto que você quiser. - Se você estiver criando um feed Atom, ao invés de um feed RSS, configure o
atributo
subtitle
ao invés do atributodescription
. Veja Publicando feeds Atom e RSS no tandem, depois, só para exemplificar.
Uma coisa que resta fazer. Num feed RSS, cada <item>
tem um <title>
,
<link>
e <description>
. Nós precisamos dizer ao framework quais dados
por nesses elementos.
Para especificar os conteúdos de
<title>
e<description>
, crie templates Django chamadosfeeds/latest_title.html
efeeds/latest_description.html
, ondelatest
é oslug
especificado no URLconf para o dado feed. Note que a extenção.html
é obrigatória. O sistema RSS renderiza este template para cada item, passando-o duas variáveis de contexto:{{ obj }}
– O objeto atual (um dos objetos que você retornou emitems()
).{{ site }}
– Um objetodjango.contrib.sites.models.Site
representando o site atual. Este é útil para{{ site.domain }}
ou{{ site.name }}
. Se você não tem o framework Django sites instalado, isso será setado com um objetodjango.contrib.sites.models.RequestSite
. Veja a a seção RequestSite da documentação do framework sites para mais.
Se você não cirar um template para ambos título ou descrição, o framework usará o template
"{{ obj }"
por padrão – isto é, a representação normal do objeto. Você pode também mudar os nomes deste dois templates especificandotitle_template
edescription_template
como atributos de sua própria classeFeed
.Para especificar os conteúdos do
<link>
, você tem duas opções. Para cada ítem emitems()
, O Django primeiro tenta chamar o métodoitem_link()
na classeFeed
, passando-o um único parametro,item
, que ‘o objeto em si. Se este método não existe, o Django tenta executar um métodoget_absolute_url()
neste objeto. Ambosget_absolute_url()
eitem_link()
devem retornar a URL do item como uma string normal do Python. Como noget_absolute_url()
, o resultado doitem_link()
será incluído diretamente na URL, então você é responsável por fazer todo o necessário para escapar a URL e convertê-la para ASCII dentro do método.Para o exemplo LatestEntries acima, nós poderiámos ter um template de feed muito mais simples:
latest_title.html:
{{ obj.title }}
latest_description.html:
{{ obj.description }}
Um exemplo complexo¶
O framework também suporta feeds mais complexos, via paramêtros.
Por exemplo, chicagocrime.org oferece um RSS feed de crimes recentes para
cada batida policial em Chicago. Seria bobagem criar uma classe
Feed
para cada batida policial; o que
poderia violar o princípio DRY e juntamente a lógica de
programação dos dados. Ao invés, o framework deixa você fazer feeds genéricos
que mostram ítens baseados em informações da URL do feed.
No chicagocrime.org, os feeds de batidas policiais são acessíveis por URLs como estas:
/rss/beats/0613/
– Retorna crimes recentes para batida 0613./rss/beats/1424/
– Retorna crimes recentes para batida 1424.
O slug aqui é "beats" ``. O framework exerga os fragmentos extras na URL
depois do slug -- ``0613
e 1424
– e dá a você um hook para dizer-lhe o
que esses fragmentos significam, e como eles podem influênciar em quais ítens
serão publicados no feed.
Um exemplo deixará tudo mais claro. Aqui temos um código para esses feeds de batidas em específico:
from django.contrib.syndication.feeds import FeedDoesNotExist
from django.core.exceptions import ObjectDoesNotExist
class BeatFeed(Feed):
def get_object(self, bits):
# No caso de "/rss/beats/0613/foo/bar/baz/", ou outra coisa do tipo,
# checa se fragmentos possui somente um membro.
if len(bits) != 1:
raise ObjectDoesNotExist
return Beat.objects.get(beat__exact=bits[0])
def title(self, obj):
return "Chicagocrime.org: Crimes for beat %s" % obj.beat
def link(self, obj):
if not obj:
raise FeedDoesNotExist
return obj.get_absolute_url()
def description(self, obj):
return "Crimes recently reported in police beat %s" % obj.beat
def items(self, obj):
return Crime.objects.filter(beat__id__exact=obj.id).order_by('-crime_date')[:30]
Aqui temos um algorítimo básico que o framework RSS segue, dada esta classe e
uma requisição para uma URL /rss/beats/0613
:
O framework pega a URL
/rss/beats/0613/
e identidica onde há um fragmento extra na URL depois do slug. Ele separa esta string remanescente por um caracter barra ("/"
) e chama o método da classeFeed
get_object()
, passando-o os fragmentos. Neste caso, fragmentos são['0613']
. Para uma requisição como/rss/beats/0613/foo/bar/
, os fragmentos poderiam ser['0613', 'foo', 'bar']
.O
get_object()
é responsável por receber a certa batida, de um fragmento. Neste caso, ele usa a API de banco de dados do Django para receber a batida. Note queget_object()
deve lançar umdjango.core.exceptions.ObjectDoesNotExist
se os paramêtros dados forem inválidos. Não hátry
/except
numa chamadaBeat.objects.get()
, pois não é necessário; esta função lança umBeat.DoesNotExist
em caso de falha, eBeat.DoesNotExist
é uma subclassse deObjectDoesNotExist
. LançandoObjectDoesNotExist
noget_object()
diz ao Django para produzir um erro 404 para aquela requisição.get_object()
pode manipular a url/rss/beats/
.O método
get_object()
também tem a oportunidade de lidar com a url/rss/beats/
. Neste caso,bits
será uma lista vazia. No nosso exemplo,len(bits) != 1
e uma exceçãoObjectDoesNotExist
serão lançados, então/rss/beats/
gerará uma página 404. Mas você pode lidar com este caso da forma como quiser. Por exemplo, você poderia gerar um feed combinado para todas as batidas.Para gerar o
<title>
,<link>
e<description>
do feed, O Django usa os métodostitle()
,link()
edescription()
. No exemplo anterior, eles foram uma string simples num atributo da classe, mas este exemplo ilustra que eles podem ser tanto strings quanto métodos. Para cada umtitle
,link
edescription
, o Django segue este algorítimo:- Primeiro, ele tenta chamar o método, passando o argumento
obj
, ondeobj
é o objeto retornado porget_object()
. - Caso falhe, ele tenta chamar o método sem argumentos.
- Caso falhe, ele usa o atributo da classe.
Dentro do método
link()
, nós lidamos com a possibilidade de que oobj
pode serNone
, isso pode ocorrer quando a URL não foi completamente especificada. Em alguns casos, você pode querer fazer algo a mais, o que poderia significar que você precisará chegar a existência doobj
nos outros métodos também. (O métodolink()
é chamada muito antes do processo de geração do feed, então é um bom lugar para liberá-lo logo.)- Primeiro, ele tenta chamar o método, passando o argumento
Finalmente, no que
items()
nesse exemplo também recebe o argumentoobj
. O algoritmo para oitems
é o mesmo descrito no passo anterior – primeiro, ele tenta oitems(obj)()
, depoisitems()
, e finalmente o atributo da classeitems
(que deve ser uma lista).
The ExampleFeed
class below gives full documentation on methods and
attributes of Feed
classes.
Especificando o tipo de feed¶
Por padrão, o s feeds produzidos neste framework usa RSS 2.0.
Para mudar isso, adicione um atributo feed_type
na sua classe
Feed
, tipo:
from django.utils.feedgenerator import Atom1Feed
class MyFeed(Feed):
feed_type = Atom1Feed
Note que é para setar feed_type
no objeto da classe, não numa instância.
Atualmente os tipos de feed disponíveis são:
django.utils.feedgenerator.Rss201rev2Feed
(RSS 2.01. Padrão.)django.utils.feedgenerator.RssUserland091Feed
(RSS 0.91.)django.utils.feedgenerator.Atom1Feed
(Atom 1.0.)
Compartimentos¶
Para especificar compartimento, como estes usados na criação de feeds de
podcasts, use os hooks item_enclosure_url
, item_enclosure_length
e item_enclosure_mime_type
. Veja a classe ExampleFeed
abaixo para
exemplos de uso.
Language¶
Os feeds criados pelo framework syndication automaticamente incluem a tag
<language>
(RSS 2.0) ou atributo xml:lang
(Atom). Este vem diretamente
de sua configuração LANGUAGE_CODE
.
URLs¶
O método/atributo link
pode retornar tanto uma URL absoluta (e.g.
"/blog/"
) quanto uma URL completa com o domínio e protocolo (e.g.
"http://www.example.com/blog/"
). Se link
não retorna o domínio,
o framework inserirá o domínio do site atual, de acordo com a sua configuração
SITE_ID
.
O feeds Atom requerem um <link rel="self">
que define a localização do feed
atual. O framework syndication popula isso automaticamente, usando o domínio
do site atual de acordo com a configuração SITE_ID
.
Publicando feeds Atom e Rss no tandem¶
Alguns desenvolvedore disponibilizam ambos versões Atom e RSS de seus feeds.
Isso é fácil de fazer com o Django: É só criar uma subclasse para sua classe
Feed
e setar o feed_type
para
algo diferente. Então atualizar seu URLconf para adicionar as versões extras.
Aqui temos um exemplo completo:
from django.contrib.syndication.feeds import Feed
from chicagocrime.models import NewsItem
from django.utils.feedgenerator import Atom1Feed
class RssSiteNewsFeed(Feed):
title = "Chicagocrime.org site news"
link = "/sitenews/"
description = "Updates on changes and additions to chicagocrime.org."
def items(self):
return NewsItem.objects.order_by('-pub_date')[:5]
class AtomSiteNewsFeed(RssSiteNewsFeed):
feed_type = Atom1Feed
subtitle = RssSiteNewsFeed.description
Note
Neste exemplo, o feed RSS usa um description
enquanto o feed Atom
usa um subtitle
. Isso porque os feeds Atom não fornece um
“description” a nível de feed, mas eles*fornece* um “subtitle.”
Se você fornecer um description
na sua classe
Feed
, o Django não
colocará automaticamente isso dentro do elemento subtitle
, pois um
subtitle e um description não são necessáriamente a mesma coisa. Ao invés
disso, você deve definir um atributo subtitle
.
No exemplo acima, nós simplesmente setamos o sibutitle
do feed Atom
para o description
do feed RSS, pois é bastante curto já.
E o URLconf acompanhante:
from django.conf.urls.defaults import *
from myproject.feeds import RssSiteNewsFeed, AtomSiteNewsFeed
feeds = {
'rss': RssSiteNewsFeed,
'atom': AtomSiteNewsFeed,
}
urlpatterns = patterns('',
# ...
(r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed',
{'feed_dict': feeds}),
# ...
)
Referência da classe Feed¶
Este exemplo ilustra todos os possíveis atributos e métodos para uma classe
Feed
:
from django.contrib.syndication.feeds import Feed
from django.utils import feedgenerator
class ExampleFeed(Feed):
# FEED TYPE -- Opcional. Este deve ser uma classe que extende
# django.utils.feedgenerator.SyndicationFeed. Este designa qual tipo
# de feed deve ser: RSS 2.0, Atom 1.0, etc.
# Se você não especificar feed_type, seu feed será RSS 2.0.
# Este deve ser uma classe, não uma instância de classe.
feed_type = feedgenerator.Rss201rev2Feed
# TEMPLATE NAMES -- Opcional. Estes devem ser strings representando
# nome dos templates do Django que o sistema deve usar para renderizar o
# title e description de seus ítens do feed. Ambos são opcionais.
# Se você não especificar um, ou ambos, o Django usará o template
# 'feeds/SLUG_title.html' e 'feeds/SLUG_description.html', onde SLUG
# é o slug que você especificar na URL.
title_template = None
description_template = None
# TITLE -- Pelo menos um dos três é obrigatório. O framework procura por
# eles nessa ordem.
def title(self, obj):
"""
Recebe o objeto retornado por get_object() e retorna o title do feed
como uma string normal do Python.
"""
def title(self):
"""
Retorna o title do feed como uma string normal do Python.
"""
title = 'foo' # Hard-coded title.
# LINK -- Pelo menos um dos três é obrigatório. O framework procura por
# eles nessa ordem.
def link(self, obj):
"""
Recebe o objeto retornado por get_object() e retorna o link do feed
como uma string normal do Python.
"""
def link(self):
"""
Retorna o link do feed como uma string normal do Python.
"""
link = '/foo/bar/' # Hard-coded link.
# GUID -- Pelo menos um dos três é opcional. O framework procura por
# eles nesta ordem. Esta propriedade é somente usada em feeds Atom
# (onde é o ID do elemento no nível do feed). Se não for fornecido, o
# link do feed é usado como um ID.
def feed_guid(self, obj):
"""
Recebe um objeto retornado por get_object() e retorna o ID único
global para o feed como uma string normal do Python.
"""
def feed_guid(self):
"""
Retorna o ID único global do feed como uma string normal do Python.
"""
feed_guid = '/foo/bar/1234' # Hard-coded guid.
# DESCRIPTION -- Pelo menos um dos três é obrigatório. O framework
# procura por eles nesta ordem.
def description(self, obj):
"""
Recebe o objeto retornado pelo get_object() e retorna o description
do feed como uma string normal do Python.
"""
def description(self):
"""
Retorna o description do feed como uma string normal do Python.
"""
description = 'Foo bar baz.' # Hard-coded description.
# AUTHOR NAME -- Pelo menos um dos três é opcional. O framework procura
# por eles nesta ordem.
def author_name(self, obj):
"""
Recebe um objeto retornado por get_object() e retorna o nome do
autor do feed como uma string normal do Python.
"""
def author_name(self):
"""
Retorna o nome do autor do feed como uma string normal do Python.
"""
author_name = 'Sally Smith' # Hard-coded author name.
# AUTHOR E-MAIL --Pelo menos um dos três é opcional. O framework procura
# por eles nesta ordem.
def author_email(self, obj):
"""
Recebe um objeto retornado por get_object() e retorna o e-mail do
autor como uma string normal do Python.
"""
def author_email(self):
"""
Retorna o e-mail do autor como uma string normal do Python.
"""
author_email = 'test@example.com' # Hard-coded author e-mail.
# AUTHOR LINK --Pelo menos um dos três é opcional. O framework
# procura por eles nessa ordem. Em cada caso, a URL deve incluir
# o "http://" e o nome do domínio.
def author_link(self, obj):
"""
Recebe o objeto retornado por get_object() e retorna a URL do autor
do feed como uma string normal do Python.
"""
def author_link(self):
"""
Retorna a URL do autor do feed como uma string normal do Python.
"""
author_link = 'http://www.example.com/' # Hard-coded author URL.
# CATEGORIES -- Pelo menos um dos três é opcional. O framework
# procura por eles nessa ordem. Em cada caso, o método/atributo
# deve retornar um objeto iterável que retorna strings.
def categories(self, obj):
"""
Recebe o objeto retornado por get_object() e retorna as categorias
do feed como iteráveis sobre strings.
"""
def categories(self):
"""
Retorna as categorias do feed como iteráveis sobre strings.
"""
categories = ("python", "django") # Hard-coded list of categories.
# COPYRIGHT NOTICE -- Pelo menos um dos três é opcional. O framework
# procura por eles nessa ordem..
def copyright(self, obj):
"""
Recebe o objeto retornado por get_object() e retorna o aviso de
copyright do feed como uma string normal do Python.
"""
def copyright(self):
"""
Retorna o aviso de copyright do feed como uma string normal do
Python.
"""
copyright = 'Copyright (c) 2007, Sally Smith' # Hard-coded copyright notice.
# TTL -- Pelo menos um dos três é opcional. O framework procura por eles
# nessa ordem. Ignorado por feeds Atom.
def ttl(self, obj):
"""
Recebe o objeto retornado por get_object() e retorna o TTL (Tempo de
vida) do feed como uma string normal do Python.
"""
def ttl(self):
"""
Retorna o TTL do feed como uma string normal do Python.
"""
ttl = 600 # Hard-coded Time To Live.
# ITEMS -- Pelo menos um dos três é obrigatório. O framework procura
# por eles nessa ordem.
def items(self, obj):
"""
Recebe o objeto retornado por get_object() e retorna uma lista de
ítens para publicar nesse feed.
"""
def items(self):
"""
Retorna uma lista de ítens para publicar neste feed.
"""
items = ('Item 1', 'Item 2') # Hard-coded items.
# GET_OBJECT -- Esse é obrigatório para feeds que publicam diferentes
# dados para diferentes parâmetros de URL. (Veja "Um exemplo complexo"
# acima.)
def get_object(self, bits):
"""
Recebe uma lista de strings recolhidos de uma URL e retorna um
objeto representado por este feed. Lança
django.core.exceptions.ObjectDoesNotExist sobre erro.
"""
# ITEM LINK -- Pelo menos um dos três é obrigatório. O framework procura
# por eles nessa ordem.
# Primeiro, o framework tenta os dois métodos abaixo, na ordem.
# Caso falhem, ele cai de volta para no método get_absolute_url()
# de cada item retornado por items().
def item_link(self, item):
"""
Recebe um item, como retornado por items(), e retorna a URL do item.
"""
def item_link(self):
"""
Retorna a URL para todo item no feed.
"""
# ITEM_GUID -- O seguinte método é opcional. Se não fornecido, o link
# do item é usado por padrão.
def item_guid(self, obj):
"""
Recebe um item, como retornado por items(), e retorna o ID do item.
"""
# ITEM AUTHOR NAME -- Pelo menos um dos três é opcional. O framework
# procura por eles nessa ordem.
def item_author_name(self, item):
"""
Recebe um item, como retornado por items(), e retorna o nome do
autor do feed como uma string normal do Python.
"""
def item_author_name(self):
"""
Retorna o nome do autor do feed para todo item do feed.
"""
item_author_name = 'Sally Smith' # Hard-coded author name.
# ITEM AUTHOR E-MAIL --Pelo menos um dos três é opcional. O
# framework procura por eles nessa ordem.
#
# Se você especifica isso, você pode especificar item_author_name.
def item_author_email(self, obj):
"""
Recebe um item, como retornado por items(), e retorna o e-mail do
autor do feed como uma string normal do Python.
"""
def item_author_email(self):
"""
Retorna o e-mail do autor para todo item no feed.
"""
item_author_email = 'test@example.com' # Hard-coded author e-mail.
# ITEM AUTHOR LINK --Pelo menos um dos três é opcional. O
# framework procura por eles nessa ordem. Em cada caso, a URL deve
# incluir o "http://" e nome de domínio.
#
# Se você especificar isso, você deve especificar o item_author_name.
def item_author_link(self, obj):
"""
Recebe um item, como retornado por items(), e retorna a URL do autor
do item como uma string normal do Python.
"""
def item_author_link(self):
"""
Retorna a URL do autor para todo item do feed.
"""
item_author_link = 'http://www.example.com/' # Hard-coded author URL.
# ITEM ENCLOSURE URL -- Pelo menos um dos três é obrigatório se você
# estiver publicando compartimentos. O framework procura por eles nessa
# ordem..
def item_enclosure_url(self, item):
"""
Recebe um item, como retornado por items(), e retorna o
URL de compartimento do item.
"""
def item_enclosure_url(self):
"""
Retorna a URL do compartimento para todo item do feed.
"""
item_enclosure_url = "/foo/bar.mp3" # Hard-coded enclosure link.
# ITEM ENCLOSURE LENGTH -- Pelo menos um dos três é obrigatório se você
# estiver publicando compartimentos. O framework procura por eles nessa
# ordem. Em cada caso, o valor retornado deve ser um inteiro, ou uma
# representação em string de um inteiro, em bytes.
def item_enclosure_length(self, item):
"""
Recebe um item, como retornado por items(), e retorna o comprimento
do compartimento do item.
"""
def item_enclosure_length(self):
"""
Retorna o comprimento do compartimento do item para todo item no
feed.
"""
item_enclosure_length = 32000 # Hard-coded enclosure length.
# ITEM ENCLOSURE MIME TYPE -- Pelo menos um dos três é obrigatório se
# você estiver publicando compartimentos. O framework procura por eles
# nessa ordem.
def item_enclosure_mime_type(self, item):
"""
Recebe um item, como retornado por items(), e retorna o tipo MIME do
compartimento do item.
"""
def item_enclosure_mime_type(self):
"""
Returns the enclosure MIME type for every item in the feed.
"""
item_enclosure_mime_type = "audio/mpeg" # Hard-coded enclosure MIME type.
# ITEM PUBDATE -- É opcional para usar um dos três. Este é um hook
# que especifica como obter a data de um dado item.
# Em cada caso, o método/atributo deve retornar um objeto
# datetime.datetime do Python.
def item_pubdate(self, item):
"""
Recebe um item, como retornado por items(), e retorna o pubdate do
item.
"""
def item_pubdate(self):
"""
Retorna o pubdate para todo item do feed.
"""
item_pubdate = datetime.datetime(2005, 5, 3) # Hard-coded pubdate.
# ITEM CATEGORIES -- É opcional usar um dos três. Este é um hook que
# especifica como obter a lista de categorias para um dado item.
# Em cada caso, o método/atributo deve retorna um objeto iterável que
# retorna strings.
def item_categories(self, item):
"""
Recebe um item, como retornado por items(), e retorna as categorias
do item.
"""
def item_categories(self):
"""
Retorna as categorias para cada item no feed.
"""
item_categories = ("python", "django") # Hard-coded categories.
# ITEM COPYRIGHT NOTICE (somente aplicável a feeds Atom) -- Pelo menos
# um dos três é opcional. O framework procura por eles nessa ordem.
def item_copyright(self, obj):
"""
Recebe um item, como retornado por items(), e retorna o aviso de
copyright do item como uma string normal do Python.
"""
def item_copyright(self):
"""
Retorna o aviso de copyright para todo item no feed.
"""
item_copyright = 'Copyright (c) 2007, Sally Smith' # Hard-coded copyright notice.
O framework de baixo nível¶
Por trás das cenas, o framework RSS de alto nível usa o framework de baixo nível para gerar o XML do feed. Este framework fica num único módulo: django/utils/feedgenerator.py.
Você usa este framework você mesmo, para geração de feed de baixo nível. Você
pode também criar um gerador de feed personalizado extendendo-o para usar com
a opção feed_type
do Feed
.
Classes SyndicationFeed
¶
O módulo feedgenerator
contém uma classe base:
e várias subclasses:
Cada uma dessas três classes sabe como renderizar um certo tipo de feed como XML. Elas compartilham essa interface:
Inicia o feed com o dicionário de metadado fornecido, que é aplicado ao feed todo. Os argumento nomeados obrigatórios são:
title
link
description
Também existe um conjunto de outros argumentos opções:
language
author_email
author_name
author_link
subtitle
categories
feed_url
feed_copyright
feed_guid
ttl
Qualquer argumento extra que você passar para o
__init__
será armazenado noself.feed
para uso com geradores de feed personalizados.Todos os paramêtros devem ser objetos Unicode, exceto
categories
, que deve ser uma sequência de objetos Unicode.
Adiciona um item ao feed com os dados paramêtros.
Os Argumentos requeridos são:
title
link
description
O argumentos opcionais são:
author_email
author_name
author_link
pubdate
comments
unique_id
enclosure
categories
item_copyright
ttl
Argumentos extra serão armazenados para geradores de feed personalizados.
Todos os parametros, se fornecidos, devem ser objetos Unicode, exceto:
pubdate
deve ser um objeto datetime do Python.enclosure
deve ser uma instância dofeedgenerator.Enclosure
.categories
deve ser uma sequência de objetos Unicode.
Mostra o feed na codificação fornecida para o outfile, que é um objeto tipo arquivo.
Retorna o feed como uma string numa dada codificação.
Por exemplo, para criar um Atom 1.0 e imprimi-lo na saída padrão:
>>> from django.utils import feedgenerator
>>> f = feedgenerator.Atom1Feed(
... title=u"My Weblog",
... link=u"http://www.example.com/",
... description=u"In which I write about what I ate today.",
... language=u"en")
>>> f.add_item(title=u"Hot dog today",
... link=u"http://www.example.com/entries/1/",
... description=u"<p>Today I had a Vienna Beef hot dog. It was pink, plump and perfect.</p>")
>>> print f.writeString('UTF-8')
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
...
</feed>
Geradores de feed personalizados¶
Se você precisa produzir um formato de feed personalizado, você tem algumas opções.
Se o formato do feed é totalmente personalizado, você poderia extender o
SyndicationFeed
e substituir completamente os métodos write()
e
writeString()
.
No entanto, se o formato do feed é um spin-off de RSS ou Atom (i.e. GeoRSS,
formato iTunes podcast da Apple, etc.) você tem uma escolha melhor. Esses
tipos de feeds tipicamente adicionam elementos extra e/ou atributos ao formato
subjacente, e há um conjunto de métodos que SyndicationFeed
chama para obter
estes atributos extra. Deste modo, você pode extender a classe geradora de feed
apropriada (Atom1Feed
ou rss201rev2Feed
) e extender estes callbacks.
São eles:
SyndicationFeed.root_attributes(self, )
- Retorna um
dict
de atributos para adicionar ao elemento raiz do feed. (feed
/channel
). SyndicationFeed.add_root_elements(self, handler)
- Callback para adicionar elementos dentro do elemento raiz do feed
(
feed
/channel
).handler
é um XMLGenerator da biblioteca SAX built-in do Python; você poderia chamar métodos sobre ela para adicionar o documento XML no processo. SyndicationFeed.item_attributes(self, item)
- Retorna um
dict
de atributos para adicionar a cada item (item
/entry
). O argumento,item
, é um dicionário com todos os dados passados aoSyndicationFeed.add_item()
. SyndicationFeed.add_item_elements(self, handler, item)
- Callback para adicionar elementos a cada item (
item
/entry
).handler
eitem
são como mostrado acima.
Warning
Se você sobrescrever qualquer um destes métodos, esteja seguro de chamar os métodos da superclasse de modo que eles adicionem os elementos obrigatórios para cada formato de feed.
Por exemplo, você pode começar a implementando um gerador de feed iTunes RSS desta forma:
class iTunesFeed(Rss201rev2Feed):
def root_attributes(self):
attrs = super(iTunesFeed, self).root_attributes()
attrs['xmlns:itunes'] = 'http://www.itunes.com/dtds/podcast-1.0.dtd'
return attrs
def add_root_elements(self, handler):
super(iTunesFeed, self).add_root_elements(handler)
handler.addQuickElement('itunes:explicit', 'clean')
Obviamente há um monte de trabaho a ser feito para uma classe de feed personalizada completa, mas o exemplo acima deve demonstrar a idéia básica.