Django viene con un marco de alto nivel para generar feeds RSS y Atom.
Para crear cualquier feed de syndication, solo tienes que escribir una clase Python breve. Puedes crear tantos feeds como desees.
Django también viene con una API de generación de feeds de bajo nivel. Utiliza esta si deseas generar feeds fuera del contexto web o de alguna otra manera más baja.
El framework de generación de feeds a nivel alto está proporcionado por la clase Feed. Para crear un feed, escribe una clase Feed y apunta a una instancia de ella en tu URLconf.
Feed¶Una clase Feed es una clase Python que representa un feed de sindicación. Un feed puede ser simple (por ejemplo, un «feed de noticias del sitio» o un feed básico que muestra las últimas entradas de un blog) o más complejo (por ejemplo, un feed que muestra todas las entradas de un blog en una categoría particular, donde la categoría es variable).
Las clases Feed heredan de django.contrib.syndication.views.Feed. Pueden vivir en cualquier parte de tu base de código.
Instancias de las clases Feed son vistas que se pueden utilizar en tu URLconf.
Este ejemplo simple, tomado de un sitio hipotético de noticias de policía describe un feed de los últimos cinco artículos de noticias:
from django.contrib.syndication.views import Feed
from django.urls import reverse
from policebeat.models import NewsItem
class LatestEntriesFeed(Feed):
title = "Police beat site news"
link = "/sitenews/"
description = "Updates on changes and additions to police beat central."
def items(self):
return NewsItem.objects.order_by("-pub_date")[:5]
def item_title(self, item):
return item.title
def item_description(self, item):
return item.description
# item_link is only needed if NewsItem has no get_absolute_url method.
def item_link(self, item):
return reverse("news-item", args=[item.pk])
Para conectar una URL a este feed, coloca una instancia del objeto Feed en tu URLconf. Por ejemplo:
from django.urls import path
from myproject.feeds import LatestEntriesFeed
urlpatterns = [
# ...
path("latest/feed/", LatestEntriesFeed()),
# ...
]
Nota:
La clase Feed hereda de django.contrib.syndication.views.Feed.
title, link y description corresponden a los elementos RSS estándar <title>, <link> y <description>, respectivamente.
items() es un método que devuelve una lista de objetos que deben incluirse en la fuente como elementos <item>. Aunque este ejemplo devuelve objetos NewsItem utilizando el mapeador objeto-relacional de Django :doc:` </ref/models/querysets>`, items() no necesita devolver instancias de modelos. Aunque se obtiene un poco de funcionalidad «de forma gratuita» al utilizar modelos de Django, items() puede devolver cualquier tipo de objeto que desee.
Si estás creando un feed de Atom en lugar de uno de RSS, establece la atributo subtitle en lugar del atributo description. Consulta Publicar feeds de Atom y RSS simultáneamente , más adelante, para un ejemplo.
Una cosa queda por hacer. En un feed RSS, cada <item> tiene un <title>, <link> y <description>. Necesitamos decirle al marco qué datos poner en esos elementos.
Para los contenidos de <title> y <description>, Django intenta llamar a los métodos item_title() y item_description() en la clase Feed. Se les pasa un parámetro, item, que es el objeto mismo. Estos son opcionales; por defecto, se utiliza la representación como cadena del objeto para ambos.
Si deseas realizar algún formato especial para el título o la descripción, se pueden utilizar los plantillas de Django en lugar de eso: Django templates <ref/templates/language> . Sus rutas se pueden especificar con las atributos title_template y description_template en la clase Feed. Las plantillas se renderizan para cada item y se pasan dos variables de contexto de plantilla:
obj – El objeto actual (uno de los objetos que devolviste en items()).
{{ site }} – Un objeto django.contrib.sites.models.Site que representa el sitio actual. Esto es útil para {{ site.domain }} o {{ site.name }}. Si no tienes instalado el framework de sitios de Django, esto se establecerá en un objeto RequestSite. Consulta la sección del documento de referencia del framework de sitios sobre objetos RequestSite para más información.
Ver el ejemplo complejo abajo, que utiliza un plantilla de descripción.
Hay también una forma de pasar información adicional a los plantillas de título y descripción, si necesitas suministrar más que las dos variables mencionadas anteriormente. Puedes proporcionar tu implementación del método get_context_data en tu subclase de Feed. Por ejemplo:
from mysite.models import Article
from django.contrib.syndication.views import Feed
class ArticlesFeed(Feed):
title = "My articles"
description_template = "feeds/articles.html"
def items(self):
return Article.objects.order_by("-pub_date")[:5]
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["foo"] = "bar"
return context
Y el plantilla:
Something about {{ foo }}: {{ obj.description }}
Este método se llamará una vez por cada elemento en la lista devuelta por items() con los siguientes argumentos de palabra clave:
item: el elemento actual. Por razones de compatibilidad hacia atrás, el nombre de esta variable de contexto es {{ obj }}.
obj: el objeto devuelto por get_object(). Por defecto, este no se expone a los templates para evitar confusiones con {{ obj }} (consulte arriba), pero puedes utilizarlo en tu implementación de get_context_data().
sitio: sitio actual tal como se describe arriba.
solicitud: solicitud actual.
El comportamiento de get_context_data() imita el de las vistas genericas <adding-extra-context> - debes llamar a super() para recuperar los datos de contexto de la clase padre, agregar tus datos y devolver el diccionario modificado.
Para especificar el contenido de <link>, tienes dos opciones. Para cada elemento en items(), Django intenta primero llamar al método item_link() en la clase Feed. De manera similar a título y descripción, se le pasa un parámetro único, item. Si ese método no existe, Django intenta ejecutar el método get_absolute_url() en ese objeto. Ambos get_absolute_url() y item_link() deben devolver la URL del elemento como una cadena de Python normal. Al igual que con get_absolute_url(), el resultado de item_link() se incluirá directamente en la URL, por lo que eres responsable de realizar todas las necesarias citación de URL y conversión a ASCII dentro del método mismo.
El marco también admite feeds más complejos mediante argumentos.
Por ejemplo, un sitio web podría ofrecer una fuente RSS de crímenes recientes para cada barrio policial en una ciudad. Sería tonto crear una clase Feed separada para cada barrio policial; eso violaría el principio <dry> y acoplaría datos a la lógica de programación. En su lugar, el marco de syndication te permite acceder a los argumentos pasados desde tu URLconf para que las fuentes puedan producir elementos basándose en información en la URL de la fuente.
Las fuentes de policía podrían estar accesibles a través de URLs como esta:
/beats/613/rss/ – Devuelve crímenes recientes para el barrio 613.
/beats/1424/rss/ – Devuelve crímenes recientes para el barrio 1424.
Estos se pueden coincidir con una línea como :doc:`<em>URLconf</em> <a class=»reference internal» href=»/topics/http/urls/» rel=»nofollow»><span class=»std std-ref»>http/urls</span></a>
path("beats/<int:beat_id>/rss/", BeatFeed()),
Como una vista, los argumentos en la URL se pasan al método get_object() junto con el objeto de solicitud.
Aquí tienes el código para estas fuentes específicas de ritmo:
from django.contrib.syndication.views import Feed
class BeatFeed(Feed):
description_template = "feeds/beat_description.html"
def get_object(self, request, beat_id):
return Beat.objects.get(pk=beat_id)
def title(self, obj):
return "Police beat central: Crimes for beat %s" % obj.beat
def link(self, obj):
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=obj).order_by("-crime_date")[:30]
Para generar el feed de <title>, <link> y <description>, Django utiliza los métodos title(), link() y description(). En el ejemplo anterior, eran atributos de clase de cadena, pero este ejemplo muestra que pueden ser tanto cadenas como métodos. Para cada uno de title, link y description, Django sigue este algoritmo:
Primero, intenta llamar un método, pasando el argumento obj, donde obj es el objeto devuelto por get_object().
Fallando eso, intenta llamar un método sin argumentos.
Fallando eso, utiliza la atributo de clase.
Los métodos items() también siguen el mismo algoritmo – primero, intenta items(obj), luego items(), y finalmente un atributo de clase items (que debería ser una lista).
Estamos utilizando un template para las descripciones de los elementos. Puede ser tan mínimo como este:
{{ obj.description }}
Sin embargo, estás libre de agregar formato según tus deseos.
La clase ExampleFeed a continuación proporciona documentación completa sobre métodos y atributos de clases Feed.
Por defecto, los feeds producidos en este framework utilizan RSS 2.0.
Para cambiar eso, agrega un atributo feed_type a tu clase Feed, como se muestra a continuación:
from django.utils.feedgenerator import Atom1Feed
class MyFeed(Feed):
feed_type = Atom1Feed
Ten en cuenta que debes establecer feed_type en una objeto de clase, no en una instancia.
Los tipos de feed disponibles actualmente son:
django.utils.feedgenerator.Rss201rev2Feed (RSS 2.01. Por defecto.)
django.utils.feedgenerator.RssUserland091Feed (RSS 0.91.)
django.utils.feedgenerator.Atom1Feed (Atom 1.0.)
Para especificar enclosures, como las utilizadas en la creación de feeds de podcast, utilice el hook item_enclosures o, alternativamente y si solo tiene una enclosure por item, los hooks item_enclosure_url, item_enclosure_length y item_enclosure_mime_type. Consulte el ejemplo del clase ExampleFeed a continuación para ver ejemplos de uso.
Los feeds creados por el marco de trabajo de sindicación incluyen automáticamente la etiqueta <language> (RSS 2.0) o el atributo xml:lang (Atom). Por defecto, esto es django.utils.translation.get_language(). Puede cambiarlo estableciendo la clase language.
El método/atributo link puede devolver una ruta absoluta (por ejemplo, "/blog/") o una URL con el dominio y protocolo completamente calificados (por ejemplo, "https://www.example.com/blog/"). Si link no devuelve el dominio, el marco de trabajo de sindicación insertará el dominio del sitio actual según su SITE_ID configuración.
Los feeds Atom requieren un <link rel="self"> que define la ubicación actual del feed. El marco de trabajo de sindicación lo poblará automáticamente, utilizando el dominio del sitio actual según la SITE_ID configuración.
Algunos desarrolladores prefieren hacer disponibles tanto las versiones Atom como RSS de sus feeds. Para ello puede crear una subclase de su clase Feed y establecer el atributo feed_type a algo diferente. Luego actualice su archivo de configuración URL para agregar las versiones adicionales.
Aquí tienes un ejemplo completo:
from django.contrib.syndication.views import Feed
from policebeat.models import NewsItem
from django.utils.feedgenerator import Atom1Feed
class RssSiteNewsFeed(Feed):
title = "Police beat site news"
link = "/sitenews/"
description = "Updates on changes and additions to police beat central."
def items(self):
return NewsItem.objects.order_by("-pub_date")[:5]
class AtomSiteNewsFeed(RssSiteNewsFeed):
feed_type = Atom1Feed
subtitle = RssSiteNewsFeed.description
Nota
En este ejemplo, la fuente RSS utiliza una description, mientras que la fuente Atom utiliza un subtitle. Eso se debe a que las fuentes Atom no proporcionan una «descripción» a nivel de fuente, pero sí proporcionan una «subtítulo».
Si proporcionas una description en tu clase Feed, Django no pondrá automáticamente eso en el elemento subtitle, porque un subtítulo y una descripción no son necesariamente lo mismo. En su lugar, debes definir un atributo subtitle.
En el ejemplo anterior, establecemos la subtitle del feed de Atom en la description del feed RSS, ya que es bastante corta ya.
La URLconf asociada es:
from django.urls import path
from myproject.feeds import AtomSiteNewsFeed, RssSiteNewsFeed
urlpatterns = [
# ...
path("sitenews/rss/", RssSiteNewsFeed()),
path("sitenews/atom/", AtomSiteNewsFeed()),
# ...
]
Feed¶Este ejemplo ilustra todos los atributos y métodos posibles para una clase Feed.
from django.contrib.syndication.views import Feed
from django.utils import feedgenerator
class ExampleFeed(Feed):
# FEED TYPE -- Optional. This should be a class that subclasses
# django.utils.feedgenerator.SyndicationFeed. This designates
# which type of feed this should be: RSS 2.0, Atom 1.0, etc. If
# you don't specify feed_type, your feed will be RSS 2.0. This
# should be a class, not an instance of the class.
feed_type = feedgenerator.Rss201rev2Feed
# TEMPLATE NAMES -- Optional. These should be strings
# representing names of Django templates that the system should
# use in rendering the title and description of your feed items.
# Both are optional. If a template is not specified, the
# item_title() or item_description() methods are used instead.
title_template = None
description_template = None
# LANGUAGE -- Optional. This should be a string specifying a language
# code. Defaults to django.utils.translation.get_language().
language = "de"
# TITLE -- One of the following three is required. The framework
# looks for them in this order.
def title(self, obj):
"""
Takes the object returned by get_object() and returns the
feed's title as a normal Python string.
"""
def title(self):
"""
Returns the feed's title as a normal Python string.
"""
title = "foo" # Hard-coded title.
# LINK -- One of the following three is required. The framework
# looks for them in this order.
def link(self, obj):
"""
# Takes the object returned by get_object() and returns the URL
# of the HTML version of the feed as a normal Python string.
"""
def link(self):
"""
Returns the URL of the HTML version of the feed as a normal Python
string.
"""
link = "/blog/" # Hard-coded URL.
# FEED_URL -- One of the following three is optional. The framework
# looks for them in this order.
def feed_url(self, obj):
"""
# Takes the object returned by get_object() and returns the feed's
# own URL as a normal Python string.
"""
def feed_url(self):
"""
Returns the feed's own URL as a normal Python string.
"""
feed_url = "/blog/rss/" # Hard-coded URL.
# GUID -- One of the following three is optional. The framework looks
# for them in this order. This property is only used for Atom feeds
# (where it is the feed-level ID element). If not provided, the feed
# link is used as the ID.
def feed_guid(self, obj):
"""
Takes the object returned by get_object() and returns the globally
unique ID for the feed as a normal Python string.
"""
def feed_guid(self):
"""
Returns the feed's globally unique ID as a normal Python string.
"""
feed_guid = "/foo/bar/1234" # Hard-coded guid.
# DESCRIPTION -- One of the following three is required. The framework
# looks for them in this order.
def description(self, obj):
"""
Takes the object returned by get_object() and returns the feed's
description as a normal Python string.
"""
def description(self):
"""
Returns the feed's description as a normal Python string.
"""
description = "Foo bar baz." # Hard-coded description.
# AUTHOR NAME --One of the following three is optional. The framework
# looks for them in this order.
def author_name(self, obj):
"""
Takes the object returned by get_object() and returns the feed's
author's name as a normal Python string.
"""
def author_name(self):
"""
Returns the feed's author's name as a normal Python string.
"""
author_name = "Sally Smith" # Hard-coded author name.
# AUTHOR EMAIL --One of the following three is optional. The framework
# looks for them in this order.
def author_email(self, obj):
"""
Takes the object returned by get_object() and returns the feed's
author's email as a normal Python string.
"""
def author_email(self):
"""
Returns the feed's author's email as a normal Python string.
"""
author_email = "test@example.com" # Hard-coded author email.
# AUTHOR LINK --One of the following three is optional. The framework
# looks for them in this order. In each case, the URL should include
# the scheme (such as "https://") and domain name.
def author_link(self, obj):
"""
Takes the object returned by get_object() and returns the feed's
author's URL as a normal Python string.
"""
def author_link(self):
"""
Returns the feed's author's URL as a normal Python string.
"""
author_link = "https://www.example.com/" # Hard-coded author URL.
# CATEGORIES -- One of the following three is optional. The framework
# looks for them in this order. In each case, the method/attribute
# should return an iterable object that returns strings.
def categories(self, obj):
"""
Takes the object returned by get_object() and returns the feed's
categories as iterable over strings.
"""
def categories(self):
"""
Returns the feed's categories as iterable over strings.
"""
categories = ["python", "django"] # Hard-coded list of categories.
# COPYRIGHT NOTICE -- One of the following three is optional. The
# framework looks for them in this order.
def feed_copyright(self, obj):
"""
Takes the object returned by get_object() and returns the feed's
copyright notice as a normal Python string.
"""
def feed_copyright(self):
"""
Returns the feed's copyright notice as a normal Python string.
"""
feed_copyright = "Copyright (c) 2007, Sally Smith" # Hard-coded copyright notice.
# TTL -- One of the following three is optional. The framework looks
# for them in this order. Ignored for Atom feeds.
def ttl(self, obj):
"""
Takes the object returned by get_object() and returns the feed's
TTL (Time To Live) as a normal Python string.
"""
def ttl(self):
"""
Returns the feed's TTL as a normal Python string.
"""
ttl = 600 # Hard-coded Time To Live.
# STYLESHEETS -- Optional. To set, provide one of the following three.
# The framework looks for them in this order.
def stylesheets(self, obj):
"""
Takes the object returned by get_object() and returns the feed's
stylesheets (as URL strings or as Stylesheet instances).
"""
def stylesheets(self):
"""
Returns the feed's stylesheets (as URL strings or Stylesheet
instances).
"""
# Hardcoded stylesheets.
stylesheets = ["/stylesheet1.xsl", "stylesheet2.xsl"]
# ITEMS -- One of the following three is required. The framework looks
# for them in this order.
def items(self, obj):
"""
Takes the object returned by get_object() and returns a list of
items to publish in this feed.
"""
def items(self):
"""
Returns a list of items to publish in this feed.
"""
items = ["Item 1", "Item 2"] # Hard-coded items.
# GET_OBJECT -- This is required for feeds that publish different data
# for different URL parameters. (See "A complex example" above.)
def get_object(self, request, *args, **kwargs):
"""
Takes the current request and the arguments from the URL, and
returns an object represented by this feed. Raises
django.core.exceptions.ObjectDoesNotExist on error.
"""
# ITEM TITLE AND DESCRIPTION -- If title_template or
# description_template are not defined, these are used instead. Both are
# optional, by default they will use the string representation of the
# item.
def item_title(self, item):
"""
Takes an item, as returned by items(), and returns the item's
title as a normal Python string.
"""
def item_title(self):
"""
Returns the title for every item in the feed.
"""
item_title = "Breaking News: Nothing Happening" # Hard-coded title.
def item_description(self, item):
"""
Takes an item, as returned by items(), and returns the item's
description as a normal Python string.
"""
def item_description(self):
"""
Returns the description for every item in the feed.
"""
item_description = "A description of the item." # Hard-coded description.
def get_context_data(self, **kwargs):
"""
Returns a dictionary to use as extra context if either
description_template or item_template are used.
Default implementation preserves the old behavior
of using {'obj': item, 'site': current_site} as the context.
"""
# ITEM LINK -- One of these three is required. The framework looks for
# them in this order.
# First, the framework tries the two methods below, in
# order. Failing that, it falls back to the get_absolute_url()
# method on each item returned by items().
def item_link(self, item):
"""
Takes an item, as returned by items(), and returns the item's URL.
"""
def item_link(self):
"""
Returns the URL for every item in the feed.
"""
# ITEM_GUID -- The following method is optional. If not provided, the
# item's link is used by default.
def item_guid(self, obj):
"""
Takes an item, as return by items(), and returns the item's ID.
"""
# ITEM_GUID_IS_PERMALINK -- The following method is optional. If
# provided, it sets the 'isPermaLink' attribute of an item's
# GUID element. This method is used only when 'item_guid' is
# specified.
def item_guid_is_permalink(self, obj):
"""
Takes an item, as returned by items(), and returns a boolean.
"""
item_guid_is_permalink = False # Hard coded value
# ITEM AUTHOR NAME -- One of the following three is optional. The
# framework looks for them in this order.
def item_author_name(self, item):
"""
Takes an item, as returned by items(), and returns the item's
author's name as a normal Python string.
"""
def item_author_name(self):
"""
Returns the author name for every item in the feed.
"""
item_author_name = "Sally Smith" # Hard-coded author name.
# ITEM AUTHOR EMAIL --One of the following three is optional. The
# framework looks for them in this order.
#
# If you specify this, you must specify item_author_name.
def item_author_email(self, obj):
"""
Takes an item, as returned by items(), and returns the item's
author's email as a normal Python string.
"""
def item_author_email(self):
"""
Returns the author email for every item in the feed.
"""
item_author_email = "test@example.com" # Hard-coded author email.
# ITEM AUTHOR LINK -- One of the following three is optional. The
# framework looks for them in this order. In each case, the URL should
# include the scheme (such as "https://") and domain name.
#
# If you specify this, you must specify item_author_name.
def item_author_link(self, obj):
"""
Takes an item, as returned by items(), and returns the item's
author's URL as a normal Python string.
"""
def item_author_link(self):
"""
Returns the author URL for every item in the feed.
"""
item_author_link = "https://www.example.com/" # Hard-coded author URL.
# ITEM ENCLOSURES -- One of the following three is optional. The
# framework looks for them in this order. If one of them is defined,
# ``item_enclosure_url``, ``item_enclosure_length``, and
# ``item_enclosure_mime_type`` will have no effect.
def item_enclosures(self, item):
"""
Takes an item, as returned by items(), and returns a list of
``django.utils.feedgenerator.Enclosure`` objects.
"""
def item_enclosures(self):
"""
Returns the ``django.utils.feedgenerator.Enclosure`` list for every
item in the feed.
"""
item_enclosures = [] # Hard-coded enclosure list
# ITEM ENCLOSURE URL -- One of these three is required if you're
# publishing enclosures and you're not using ``item_enclosures``. The
# framework looks for them in this order.
def item_enclosure_url(self, item):
"""
Takes an item, as returned by items(), and returns the item's
enclosure URL.
"""
def item_enclosure_url(self):
"""
Returns the enclosure URL for every item in the feed.
"""
item_enclosure_url = "/foo/bar.mp3" # Hard-coded enclosure link.
# ITEM ENCLOSURE LENGTH -- One of these three is required if you're
# publishing enclosures and you're not using ``item_enclosures``. The
# framework looks for them in this order. In each case, the returned
# value should be either an integer, or a string representation of the
# integer, in bytes.
def item_enclosure_length(self, item):
"""
Takes an item, as returned by items(), and returns the item's
enclosure length.
"""
def item_enclosure_length(self):
"""
Returns the enclosure length for every item in the feed.
"""
item_enclosure_length = 32000 # Hard-coded enclosure length.
# ITEM ENCLOSURE MIME TYPE -- One of these three is required if you're
# publishing enclosures and you're not using ``item_enclosures``. The
# framework looks for them in this order.
def item_enclosure_mime_type(self, item):
"""
Takes an item, as returned by items(), and returns the item's
enclosure MIME type.
"""
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 -- It's optional to use one of these three. This is a
# hook that specifies how to get the pubdate for a given item.
# In each case, the method/attribute should return a Python
# datetime.datetime object.
def item_pubdate(self, item):
"""
Takes an item, as returned by items(), and returns the item's
pubdate.
"""
def item_pubdate(self):
"""
Returns the pubdate for every item in the feed.
"""
item_pubdate = datetime.datetime(2005, 5, 3) # Hard-coded pubdate.
# ITEM UPDATED -- It's optional to use one of these three. This is a
# hook that specifies how to get the updateddate for a given item.
# In each case, the method/attribute should return a Python
# datetime.datetime object.
def item_updateddate(self, item):
"""
Takes an item, as returned by items(), and returns the item's
updateddate.
"""
def item_updateddate(self):
"""
Returns the updateddate for every item in the feed.
"""
item_updateddate = datetime.datetime(2005, 5, 3) # Hard-coded updateddate.
# ITEM CATEGORIES -- It's optional to use one of these three. This is
# a hook that specifies how to get the list of categories for a given
# item. In each case, the method/attribute should return an iterable
# object that returns strings.
def item_categories(self, item):
"""
Takes an item, as returned by items(), and returns the item's
categories.
"""
def item_categories(self):
"""
Returns the categories for every item in the feed.
"""
item_categories = ["python", "django"] # Hard-coded categories.
# ITEM COPYRIGHT NOTICE (only applicable to Atom feeds) -- One of the
# following three is optional. The framework looks for them in this
# order.
def item_copyright(self, obj):
"""
Takes an item, as returned by items(), and returns the item's
copyright notice as a normal Python string.
"""
def item_copyright(self):
"""
Returns the copyright notice for every item in the feed.
"""
item_copyright = "Copyright (c) 2007, Sally Smith" # Hard-coded copyright notice.
# ITEM COMMENTS URL -- It's optional to use one of these three. This is
# a hook that specifies how to get the URL of a page for comments for a
# given item.
def item_comments(self, obj):
"""
Takes an item, as returned by items(), and returns the item's
comments URL as a normal Python string.
"""
def item_comments(self):
"""
Returns the comments URL for every item in the feed.
"""
item_comments = "https://www.example.com/comments" # Hard-coded comments URL
Detrás de escena, el marco de alto nivel para RSS utiliza un marco de bajo nivel para generar los archivos XML de las fuentes. Este marco vive en un solo módulo: django/utils/feedgenerator.py.
Utilizas este marco en tu propio proyecto para la generación de feeds a nivel bajo. También puedes crear subclases personalizadas del generador de feeds para utilizar con la opción feed_type Feed.
SyndicationFeed clases¶El módulo feedgenerator contiene una clase base:
y varias subclases:
Cada una de estas tres clases sabe cómo renderizar un tipo determinado de feed como XML. Comparten esta interfaz:
SyndicationFeed.__init__()Inicia el feed con el diccionario dado de metadatos, que se aplica a todo el feed. Los argumentos de palabra clave requeridos son:
título
link
description
Hay también una serie de otras palabras clave opcionales:
idioma
correo electrónico del autor
nombre del autor
enlace del autor
subtítulo
categorías
URL de la fuente
derechos de autor de la fuente
feed_guid
ttl
estilosheets
Cualquier argumento adicional que pases a __init__ se almacenará en self.feed para su uso con generadores de alimentación personalizados.
Todos los parámetros deben ser cadenas, excepto dos:
categorías debe ser una secuencia de cadenas.
estilosheets debe ser una secuencia de cadenas o instancias de Stylesheet.
Ten en cuenta que algunos caracteres de control no están permitidos en documentos XML. Si tu contenido contiene algunos de ellos, podrías encontrar un error ValueError cuando se produzca la alimentación.
Se agregó el argumento estilosheets.
SyndicationFeed.add_item()Añade un elemento al feed con los parámetros dados.
Los argumentos de palabra clave requeridos son:
título
link
description
Los argumentos de palabra clave opcionales son:
correo electrónico del autor
nombre del autor
enlace del autor
fecha_de_publicación
comentarios
identificador único
enclosures
categorías
derechos de autor del elemento
ttl
fecha de actualización
Los argumentos de palabra clave adicionales se almacenarán para los generadores de feeds personalizados.
Todos los parámetros, si se proporcionan, deben ser cadenas de caracteres, excepto:
SyndicationFeed.write()Imprime la fuente en el código de caracteres dado en outfile, que es un objeto similar a un archivo.
SyndicationFeed.writeString()Devuelve la fuente como una cadena en el codificado dado.
Ejemplo de cómo crear un feed Atom 1.0 y imprimirlo en la salida estándar:
>>> from django.utils import feedgenerator
>>> from datetime import datetime
>>> f = feedgenerator.Atom1Feed(
... title="My Blog",
... link="https://www.example.com/",
... description="In which I write about what I ate today.",
... language="en",
... author_name="Myself",
... feed_url="https://example.com/atom.xml",
... )
>>> f.add_item(
... title="Hot dog today",
... link="https://www.example.com/entries/1/",
... pubdate=datetime.now(),
... description="<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>
Si necesitas producir un formato de alimentación personalizado, tienes una pareja de opciones.
Si el formato de la fuente es completamente personalizado, querrás heredar de SyndicationFeed y reemplazar completamente los métodos write() y writeString().
Sin embargo, si el formato de la fuente es una derivación de RSS o Atom (es decir, GeoRSS, el formato de podcast de iTunes de Apple`_ , etc.), tienes una mejor opción. Estos tipos de fuentes suelen agregar elementos y/o atributos adicionales al formato subyacente, y hay un conjunto de métodos que SyndicationFeed llama para obtener estos atributos adicionales. Por lo tanto, puedes heredar la clase correspondiente del generador de fuentes (Atom1Feed o Rss201rev2Feed) y extender estas llamadas a funciones. Son:
Devuelve un dict de atributos para agregar al elemento raíz del feed (feed/channel).
Llamada a la función para agregar elementos dentro del elemento raíz de alimentación (feed/channel). handler es un XMLGenerator desde la biblioteca SAX incorporada de Python; llamarás métodos en él para agregar al documento XML en proceso.
Devuelve un dict de atributos para agregar a cada elemento (item/entrada). El argumento, item, es un diccionario con todos los datos pasados a SyndicationFeed.add_item().
Callback para agregar elementos a cada elemento (item/entry) del feed. handler y item son como arriba.
Advertencia
Si sobreescribes cualquier uno de estos métodos, asegúrate de llamar a los métodos de la superclase ya que agregan los elementos requeridos para cada formato de feed.
Por ejemplo, podrías empezar implementando un generador de feeds RSS iTunes como se muestra a continuación:
class iTunesFeed(Rss201rev2Feed):
def root_attributes(self):
attrs = super().root_attributes()
attrs["xmlns:itunes"] = "http://www.itunes.com/dtds/podcast-1.0.dtd"
return attrs
def add_root_elements(self, handler):
super().add_root_elements(handler)
handler.addQuickElement("itunes:explicit", "clean")
Hay mucho más trabajo por hacer para completar una clase personalizada de feed, pero el ejemplo anterior debería demostrar la idea básica.
Si deseas que tu feed RSS se renderice correctamente en un navegador, necesitarás proporcionar información de estilo para el archivo XML, típicamente en formatos XSLT o CSS.
Puedes agregar esto a tu feed RSS estableciendo la atributo stylesheets en la clase del feed.
Esto puede ser una URL hardcoded:
from django.contrib.syndication.views import Feed
class FeedWithHardcodedStylesheet(Feed):
stylesheets = [
"https://example.com/rss_stylesheet.xslt",
]
También puedes utilizar el sistema de archivos estáticos de Django:
from django.contrib.syndication.views import Feed
from django.templatetags.static import static
class FeedWithStaticFileStylesheet(Feed):
stylesheets = [
static("rss_styles.xslt"),
]
Otra opción es tener una vista en tu proyecto que renderice el documento XSLT. Puedes entonces vincularlo como se muestra a continuación:
from django.contrib.syndication.views import Feed
from django.urls import reverse_lazy
class FeedWithStylesheetView(Feed):
stylesheets = [
reverse_lazy("your-custom-view-name"),
]
Django normalmente intentará adivinar el tipo MIME del URL dado basado en su extensión, pero si eso falla puedes especificarlo utilizando la clase Stylesheet:
from django.contrib.syndication.views import Feed
from django.utils.feedgenerator import Stylesheet
class FeedWithHardcodedStylesheet(Feed):
stylesheets = [
Stylesheet("https://example.com/rss_stylesheet", mimetype="text/xsl"),
]
De manera similar, si deseas utilizar un atributo media diferente que pantalla (el valor por defecto de Django), puedes utilizar nuevamente la clase Stylesheet
from django.contrib.syndication.views import Feed
from django.utils.feedgenerator import Stylesheet
class FeedWithHardcodedStylesheet(Feed):
stylesheets = [
Stylesheet("https://example.com/rss_stylesheet.xslt", media="print"),
]
Cualquiera de estas opciones puede combinarse cuando se utilizan múltiples hojas de estilo:
from django.contrib.syndication.views import Feed
from django.utils.feedgenerator import Stylesheet
class MultiStylesheetFeed(Feed):
stylesheets = [
"/stylesheet1.xsl",
Stylesheet("/stylesheet2.xsl"),
]
may 31, 2026