thirdparty/google_appengine/lib/django/docs/syndication_feeds.txt
changeset 109 620f9b141567
equal deleted inserted replaced
108:261778de26ff 109:620f9b141567
       
     1 ==============================
       
     2 The syndication feed framework
       
     3 ==============================
       
     4 
       
     5 Django comes with a high-level syndication-feed-generating framework that makes
       
     6 creating RSS_ and Atom_ feeds easy.
       
     7 
       
     8 To create any syndication feed, all you have to do is write a short Python
       
     9 class. You can create as many feeds as you want.
       
    10 
       
    11 Django also comes with a lower-level feed-generating API. Use this if you want
       
    12 to generate feeds outside of a Web context, or in some other lower-level way.
       
    13 
       
    14 .. _RSS: http://www.whatisrss.com/
       
    15 .. _Atom: http://www.atomenabled.org/
       
    16 
       
    17 The high-level framework
       
    18 ========================
       
    19 
       
    20 Overview
       
    21 --------
       
    22 
       
    23 The high-level feed-generating framework is a view that's hooked to ``/feeds/``
       
    24 by default. Django uses the remainder of the URL (everything after ``/feeds/``)
       
    25 to determine which feed to output.
       
    26 
       
    27 To create a feed, just write a ``Feed`` class and point to it in your URLconf_.
       
    28 
       
    29 .. _URLconf: ../url_dispatch/
       
    30 
       
    31 Initialization
       
    32 --------------
       
    33 
       
    34 To activate syndication feeds on your Django site, add this line to your
       
    35 URLconf_::
       
    36 
       
    37     (r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed', {'feed_dict': feeds}),
       
    38 
       
    39 This tells Django to use the RSS framework to handle all URLs starting with
       
    40 ``"feeds/"``. (You can change that ``"feeds/"`` prefix to fit your own needs.)
       
    41 
       
    42 This URLconf line has an extra argument: ``{'feed_dict': feeds}``. Use this
       
    43 extra argument to pass the syndication framework the feeds that should be
       
    44 published under that URL.
       
    45 
       
    46 Specifically, ``feed_dict`` should be a dictionary that maps a feed's slug
       
    47 (short URL label) to its ``Feed`` class.
       
    48 
       
    49 You can define the ``feed_dict`` in the URLconf itself. Here's a full example
       
    50 URLconf::
       
    51 
       
    52     from django.conf.urls.defaults import *
       
    53     from myproject.feeds import LatestEntries, LatestEntriesByCategory
       
    54 
       
    55     feeds = {
       
    56         'latest': LatestEntries,
       
    57         'categories': LatestEntriesByCategory,
       
    58     }
       
    59 
       
    60     urlpatterns = patterns('',
       
    61         # ...
       
    62         (r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed',
       
    63             {'feed_dict': feeds}),
       
    64         # ...
       
    65     )
       
    66 
       
    67 The above example registers two feeds:
       
    68 
       
    69     * The feed represented by ``LatestEntries`` will live at ``feeds/latest/``.
       
    70     * The feed represented by ``LatestEntriesByCategory`` will live at
       
    71       ``feeds/categories/``.
       
    72 
       
    73 Once that's set up, you just need to define the ``Feed`` classes themselves.
       
    74 
       
    75 .. _URLconf: ../url_dispatch/
       
    76 .. _settings file: ../settings/
       
    77 
       
    78 Feed classes
       
    79 ------------
       
    80 
       
    81 A ``Feed`` class is a simple Python class that represents a syndication feed.
       
    82 A feed can be simple (e.g., a "site news" feed, or a basic feed displaying
       
    83 the latest entries of a blog) or more complex (e.g., a feed displaying all the
       
    84 blog entries in a particular category, where the category is variable).
       
    85 
       
    86 ``Feed`` classes must subclass ``django.contrib.syndication.feeds.Feed``. They
       
    87 can live anywhere in your codebase.
       
    88 
       
    89 A simple example
       
    90 ----------------
       
    91 
       
    92 This simple example, taken from `chicagocrime.org`_, describes a feed of the
       
    93 latest five news items::
       
    94 
       
    95     from django.contrib.syndication.feeds import Feed
       
    96     from chicagocrime.models import NewsItem
       
    97 
       
    98     class LatestEntries(Feed):
       
    99         title = "Chicagocrime.org site news"
       
   100         link = "/sitenews/"
       
   101         description = "Updates on changes and additions to chicagocrime.org."
       
   102 
       
   103         def items(self):
       
   104             return NewsItem.objects.order_by('-pub_date')[:5]
       
   105 
       
   106 Note:
       
   107 
       
   108     * The class subclasses ``django.contrib.syndication.feeds.Feed``.
       
   109     * ``title``, ``link`` and ``description`` correspond to the standard
       
   110       RSS ``<title>``, ``<link>`` and ``<description>`` elements, respectively.
       
   111     * ``items()`` is, simply, a method that returns a list of objects that
       
   112       should be included in the feed as ``<item>`` elements. Although this
       
   113       example returns ``NewsItem`` objects using Django's
       
   114       `object-relational mapper`_, ``items()`` doesn't have to return model
       
   115       instances. Although you get a few bits of functionality "for free" by
       
   116       using Django models, ``items()`` can return any type of object you want.
       
   117 
       
   118 One thing's left to do. In an RSS feed, each ``<item>`` has a ``<title>``,
       
   119 ``<link>`` and ``<description>``. We need to tell the framework what data to
       
   120 put into those elements.
       
   121 
       
   122     * To specify the contents of ``<title>`` and ``<description>``, create
       
   123       `Django templates`_ called ``feeds/latest_title.html`` and
       
   124       ``feeds/latest_description.html``, where ``latest`` is the ``slug``
       
   125       specified in the URLconf for the given feed. Note the ``.html`` extension
       
   126       is required. The RSS system renders that template for each item, passing
       
   127       it two template context variables:
       
   128 
       
   129           * ``{{ obj }}`` -- The current object (one of whichever objects you
       
   130             returned in ``items()``).
       
   131           * ``{{ site }}`` -- A ``django.models.core.sites.Site`` object
       
   132             representing the current site. This is useful for
       
   133             ``{{ site.domain }}`` or ``{{ site.name }}``.
       
   134 
       
   135       If you don't create a template for either the title or description, the
       
   136       framework will use the template ``"{{ obj }}"`` by default -- that is,
       
   137       the normal string representation of the object. You can also change the
       
   138       names of these two templates by specifying ``title_template`` and
       
   139       ``description_template`` as attributes of your ``Feed`` class.
       
   140     * To specify the contents of ``<link>``, you have two options. For each
       
   141       item in ``items()``, Django first tries executing a
       
   142       ``get_absolute_url()`` method on that object. If that method doesn't
       
   143       exist, it tries calling a method ``item_link()`` in the ``Feed`` class,
       
   144       passing it a single parameter, ``item``, which is the object itself.
       
   145       Both ``get_absolute_url()`` and ``item_link()`` should return the item's
       
   146       URL as a normal Python string.
       
   147 
       
   148     * For the LatestEntries example above, we could have very simple feed templates:
       
   149 
       
   150           * latest_title.html::
       
   151 
       
   152              {{ obj.title }}
       
   153 
       
   154           * latest_description.html::
       
   155 
       
   156              {{ obj.description }}
       
   157 
       
   158 .. _chicagocrime.org: http://www.chicagocrime.org/
       
   159 .. _object-relational mapper: ../db_api/
       
   160 .. _Django templates: ../templates/
       
   161 
       
   162 A complex example
       
   163 -----------------
       
   164 
       
   165 The framework also supports more complex feeds, via parameters.
       
   166 
       
   167 For example, `chicagocrime.org`_ offers an RSS feed of recent crimes for every
       
   168 police beat in Chicago. It'd be silly to create a separate ``Feed`` class for
       
   169 each police beat; that would violate the `DRY principle`_ and would couple data
       
   170 to programming logic. Instead, the syndication framework lets you make generic
       
   171 feeds that output items based on information in the feed's URL.
       
   172 
       
   173 On chicagocrime.org, the police-beat feeds are accessible via URLs like this:
       
   174 
       
   175     * ``/rss/beats/0613/`` -- Returns recent crimes for beat 0613.
       
   176     * ``/rss/beats/1424/`` -- Returns recent crimes for beat 1424.
       
   177 
       
   178 The slug here is ``"beats"``. The syndication framework sees the extra URL bits
       
   179 after the slug -- ``0613`` and ``1424`` -- and gives you a hook to tell it what
       
   180 those URL bits mean, and how they should influence which items get published in
       
   181 the feed.
       
   182 
       
   183 An example makes this clear. Here's the code for these beat-specific feeds::
       
   184 
       
   185     class BeatFeed(Feed):
       
   186         def get_object(self, bits):
       
   187             # In case of "/rss/beats/0613/foo/bar/baz/", or other such clutter,
       
   188             # check that bits has only one member.
       
   189             if len(bits) != 1:
       
   190                 raise ObjectDoesNotExist
       
   191             return Beat.objects.get(beat__exact=bits[0])
       
   192 
       
   193         def title(self, obj):
       
   194             return "Chicagocrime.org: Crimes for beat %s" % obj.beat
       
   195 
       
   196         def link(self, obj):
       
   197             return obj.get_absolute_url()
       
   198 
       
   199         def description(self, obj):
       
   200             return "Crimes recently reported in police beat %s" % obj.beat
       
   201 
       
   202         def items(self, obj):
       
   203             return Crime.objects.filter(beat__id__exact=obj.id).order_by('-crime_date')[:30]
       
   204 
       
   205 Here's the basic algorithm the RSS framework follows, given this class and a
       
   206 request to the URL ``/rss/beats/0613/``:
       
   207 
       
   208     * The framework gets the URL ``/rss/beats/0613/`` and notices there's
       
   209       an extra bit of URL after the slug. It splits that remaining string by
       
   210       the slash character (``"/"``) and calls the ``Feed`` class'
       
   211       ``get_object()`` method, passing it the bits. In this case, bits is
       
   212       ``['0613']``. For a request to ``/rss/beats/0613/foo/bar/``, bits would
       
   213       be ``['0613', 'foo', 'bar']``.
       
   214     * ``get_object()`` is responsible for retrieving the given beat, from the
       
   215       given ``bits``. In this case, it uses the Django database API to retrieve
       
   216       the beat. Note that ``get_object()`` should raise
       
   217       ``django.core.exceptions.ObjectDoesNotExist`` if given invalid
       
   218       parameters. There's no ``try``/``except`` around the
       
   219       ``Beat.objects.get()`` call, because it's not necessary; that function
       
   220       raises ``Beat.DoesNotExist`` on failure, and ``Beat.DoesNotExist`` is a
       
   221       subclass of ``ObjectDoesNotExist``. Raising ``ObjectDoesNotExist`` in
       
   222       ``get_object()`` tells Django to produce a 404 error for that request.
       
   223     * To generate the feed's ``<title>``, ``<link>`` and ``<description>``,
       
   224       Django uses the ``title()``, ``link()`` and ``description()`` methods. In
       
   225       the previous example, they were simple string class attributes, but this
       
   226       example illustrates that they can be either strings *or* methods. For
       
   227       each of ``title``, ``link`` and ``description``, Django follows this
       
   228       algorithm:
       
   229 
       
   230           * First, it tries to call a method, passing the ``obj`` argument, where
       
   231             ``obj`` is the object returned by ``get_object()``.
       
   232           * Failing that, it tries to call a method with no arguments.
       
   233           * Failing that, it uses the class attribute.
       
   234 
       
   235     * Finally, note that ``items()`` in this example also takes the ``obj``
       
   236       argument. The algorithm for ``items`` is the same as described in the
       
   237       previous step -- first, it tries ``items(obj)``, then ``items()``, then
       
   238       finally an ``items`` class attribute (which should be a list).
       
   239 
       
   240 The ``ExampleFeed`` class below gives full documentation on methods and
       
   241 attributes of ``Feed`` classes.
       
   242 
       
   243 .. _DRY principle: http://c2.com/cgi/wiki?DontRepeatYourself
       
   244 
       
   245 Specifying the type of feed
       
   246 ---------------------------
       
   247 
       
   248 By default, feeds produced in this framework use RSS 2.0.
       
   249 
       
   250 To change that, add a ``feed_type`` attribute to your ``Feed`` class, like so::
       
   251 
       
   252     from django.utils.feedgenerator import Atom1Feed
       
   253 
       
   254     class MyFeed(Feed):
       
   255         feed_type = Atom1Feed
       
   256 
       
   257 Note that you set ``feed_type`` to a class object, not an instance.
       
   258 
       
   259 Currently available feed types are:
       
   260 
       
   261     * ``django.utils.feedgenerator.Rss201rev2Feed`` (RSS 2.01. Default.)
       
   262     * ``django.utils.feedgenerator.RssUserland091Feed`` (RSS 0.91.)
       
   263     * ``django.utils.feedgenerator.Atom1Feed`` (Atom 1.0.)
       
   264 
       
   265 Enclosures
       
   266 ----------
       
   267 
       
   268 To specify enclosures, such as those used in creating podcast feeds, use the
       
   269 ``item_enclosure_url``, ``item_enclosure_length`` and
       
   270 ``item_enclosure_mime_type`` hooks. See the ``ExampleFeed`` class below for
       
   271 usage examples.
       
   272 
       
   273 Language
       
   274 --------
       
   275 
       
   276 Feeds created by the syndication framework automatically include the
       
   277 appropriate ``<language>`` tag (RSS 2.0) or ``xml:lang`` attribute (Atom). This
       
   278 comes directly from your `LANGUAGE_CODE setting`_.
       
   279 
       
   280 .. _LANGUAGE_CODE setting: ../settings/#language-code
       
   281 
       
   282 URLs
       
   283 ----
       
   284 
       
   285 The ``link`` method/attribute can return either an absolute URL (e.g.
       
   286 ``"/blog/"``) or a URL with the fully-qualified domain and protocol (e.g.
       
   287 ``"http://www.example.com/blog/"``). If ``link`` doesn't return the domain,
       
   288 the syndication framework will insert the domain of the current site, according
       
   289 to your `SITE_ID setting`_.
       
   290 
       
   291 Atom feeds require a ``<link rel="self">`` that defines the feed's current
       
   292 location. The syndication framework populates this automatically, using the
       
   293 domain of the current site according to the SITE_ID setting.
       
   294 
       
   295 .. _SITE_ID setting: ../settings/#site-id
       
   296 
       
   297 Publishing Atom and RSS feeds in tandem
       
   298 ---------------------------------------
       
   299 
       
   300 Some developers like to make available both Atom *and* RSS versions of their
       
   301 feeds. That's easy to do with Django: Just create a subclass of your ``feed``
       
   302 class and set the ``feed_type`` to something different. Then update your
       
   303 URLconf to add the extra versions.
       
   304 
       
   305 Here's a full example::
       
   306 
       
   307     from django.contrib.syndication.feeds import Feed
       
   308     from chicagocrime.models import NewsItem
       
   309     from django.utils.feedgenerator import Atom1Feed
       
   310 
       
   311     class RssSiteNewsFeed(Feed):
       
   312         title = "Chicagocrime.org site news"
       
   313         link = "/sitenews/"
       
   314         description = "Updates on changes and additions to chicagocrime.org."
       
   315 
       
   316         def items(self):
       
   317             return NewsItem.objects.order_by('-pub_date')[:5]
       
   318 
       
   319     class AtomSiteNewsFeed(RssSiteNewsFeed):
       
   320         feed_type = Atom1Feed
       
   321 
       
   322 And the accompanying URLconf::
       
   323 
       
   324     from django.conf.urls.defaults import *
       
   325     from myproject.feeds import RssSiteNewsFeed, AtomSiteNewsFeed
       
   326 
       
   327     feeds = {
       
   328         'rss': RssSiteNewsFeed,
       
   329         'atom': AtomSiteNewsFeed,
       
   330     }
       
   331 
       
   332     urlpatterns = patterns('',
       
   333         # ...
       
   334         (r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed',
       
   335             {'feed_dict': feeds}),
       
   336         # ...
       
   337     )
       
   338 
       
   339 Feed class reference
       
   340 --------------------
       
   341 
       
   342 This example illustrates all possible attributes and methods for a ``Feed`` class::
       
   343 
       
   344     from django.contrib.syndication.feeds import Feed
       
   345     from django.utils import feedgenerator
       
   346 
       
   347     class ExampleFeed(Feed):
       
   348 
       
   349         # FEED TYPE -- Optional. This should be a class that subclasses
       
   350         # django.utils.feedgenerator.SyndicationFeed. This designates which
       
   351         # type of feed this should be: RSS 2.0, Atom 1.0, etc.
       
   352         # If you don't specify feed_type, your feed will be RSS 2.0.
       
   353         # This should be a class, not an instance of the class.
       
   354 
       
   355         feed_type = feedgenerator.Rss201rev2Feed
       
   356 
       
   357         # TEMPLATE NAMES -- Optional. These should be strings representing
       
   358         # names of Django templates that the system should use in rendering the
       
   359         # title and description of your feed items. Both are optional.
       
   360         # If you don't specify one, or either, Django will use the template
       
   361         # 'feeds/SLUG_title.html' and 'feeds/SLUG_description.html', where SLUG
       
   362         # is the slug you specify in the URL.
       
   363 
       
   364         title_template = None
       
   365         description_template = None
       
   366 
       
   367         # TITLE -- One of the following three is required. The framework looks
       
   368         # for them in this order.
       
   369 
       
   370         def title(self, obj):
       
   371             """
       
   372             Takes the object returned by get_object() and returns the feed's
       
   373             title as a normal Python string.
       
   374             """
       
   375 
       
   376         def title(self):
       
   377             """
       
   378             Returns the feed's title as a normal Python string.
       
   379             """
       
   380 
       
   381         title = 'foo' # Hard-coded title.
       
   382 
       
   383         # LINK -- One of the following three is required. The framework looks
       
   384         # for them in this order.
       
   385 
       
   386         def link(self, obj):
       
   387             """
       
   388             Takes the object returned by get_object() and returns the feed's
       
   389             link as a normal Python string.
       
   390             """
       
   391 
       
   392         def link(self):
       
   393             """
       
   394             Returns the feed's link as a normal Python string.
       
   395             """
       
   396 
       
   397         link = '/foo/bar/' # Hard-coded link.
       
   398 
       
   399         # DESCRIPTION -- One of the following three is required. The framework
       
   400         # looks for them in this order.
       
   401 
       
   402         def description(self, obj):
       
   403             """
       
   404             Takes the object returned by get_object() and returns the feed's
       
   405             description as a normal Python string.
       
   406             """
       
   407 
       
   408         def description(self):
       
   409             """
       
   410             Returns the feed's description as a normal Python string.
       
   411             """
       
   412 
       
   413         description = 'Foo bar baz.' # Hard-coded description.
       
   414 
       
   415         # AUTHOR NAME --One of the following three is optional. The framework
       
   416         # looks for them in this order.
       
   417 
       
   418         def author_name(self, obj):
       
   419             """
       
   420             Takes the object returned by get_object() and returns the feed's
       
   421             author's name as a normal Python string.
       
   422             """
       
   423 
       
   424         def author_name(self):
       
   425             """
       
   426             Returns the feed's author's name as a normal Python string.
       
   427             """
       
   428 
       
   429         author_name = 'Sally Smith' # Hard-coded author name.
       
   430 
       
   431         # AUTHOR E-MAIL --One of the following three is optional. The framework
       
   432         # looks for them in this order.
       
   433 
       
   434         def author_email(self, obj):
       
   435             """
       
   436             Takes the object returned by get_object() and returns the feed's
       
   437             author's e-mail as a normal Python string.
       
   438             """
       
   439 
       
   440         def author_email(self):
       
   441             """
       
   442             Returns the feed's author's e-mail as a normal Python string.
       
   443             """
       
   444 
       
   445         author_email = 'test@example.com' # Hard-coded author e-mail.
       
   446 
       
   447         # AUTHOR LINK --One of the following three is optional. The framework
       
   448         # looks for them in this order. In each case, the URL should include
       
   449         # the "http://" and domain name.
       
   450 
       
   451         def author_link(self, obj):
       
   452             """
       
   453             Takes the object returned by get_object() and returns the feed's
       
   454             author's URL as a normal Python string.
       
   455             """
       
   456 
       
   457         def author_link(self):
       
   458             """
       
   459             Returns the feed's author's URL as a normal Python string.
       
   460             """
       
   461 
       
   462         author_link = 'http://www.example.com/' # Hard-coded author URL.
       
   463 
       
   464         # CATEGORIES -- One of the following three is optional. The framework
       
   465         # looks for them in this order. In each case, the method/attribute
       
   466         # should return an iterable object that returns strings.
       
   467 
       
   468         def categories(self, obj):
       
   469             """
       
   470             Takes the object returned by get_object() and returns the feed's
       
   471             categories as iterable over strings.
       
   472             """
       
   473 
       
   474         def categories(self):
       
   475             """
       
   476             Returns the feed's categories as iterable over strings.
       
   477             """
       
   478 
       
   479         categories = ("python", "django") # Hard-coded list of categories.
       
   480 
       
   481         # COPYRIGHT NOTICE -- One of the following three is optional. The
       
   482         # framework looks for them in this order.
       
   483 
       
   484         def copyright(self, obj):
       
   485             """
       
   486             Takes the object returned by get_object() and returns the feed's
       
   487             copyright notice as a normal Python string.
       
   488             """
       
   489 
       
   490         def copyright(self):
       
   491             """
       
   492             Returns the feed's copyright notice as a normal Python string.
       
   493             """
       
   494 
       
   495         copyright = 'Copyright (c) 2007, Sally Smith' # Hard-coded copyright notice.
       
   496 
       
   497         # ITEMS -- One of the following three is required. The framework looks
       
   498         # for them in this order.
       
   499 
       
   500         def items(self, obj):
       
   501             """
       
   502             Takes the object returned by get_object() and returns a list of
       
   503             items to publish in this feed.
       
   504             """
       
   505 
       
   506         def items(self):
       
   507             """
       
   508             Returns a list of items to publish in this feed.
       
   509             """
       
   510 
       
   511         items = ('Item 1', 'Item 2') # Hard-coded items.
       
   512 
       
   513         # GET_OBJECT -- This is required for feeds that publish different data
       
   514         # for different URL parameters. (See "A complex example" above.)
       
   515 
       
   516         def get_object(self, bits):
       
   517             """
       
   518             Takes a list of strings gleaned from the URL and returns an object
       
   519             represented by this feed. Raises
       
   520             django.core.exceptions.ObjectDoesNotExist on error.
       
   521             """
       
   522 
       
   523         # ITEM LINK -- One of these three is required. The framework looks for
       
   524         # them in this order.
       
   525 
       
   526         # First, the framework tries the get_absolute_url() method on each item
       
   527         # returned by items(). Failing that, it tries these two methods:
       
   528 
       
   529         def item_link(self, item):
       
   530             """
       
   531             Takes an item, as returned by items(), and returns the item's URL.
       
   532             """
       
   533 
       
   534         def item_link(self):
       
   535             """
       
   536             Returns the URL for every item in the feed.
       
   537             """
       
   538 
       
   539         # ITEM AUTHOR NAME --One of the following three is optional. The
       
   540         # framework looks for them in this order.
       
   541 
       
   542         def item_author_name(self, item):
       
   543             """
       
   544             Takes an item, as returned by items(), and returns the item's
       
   545             author's name as a normal Python string.
       
   546             """
       
   547 
       
   548         def item_author_name(self):
       
   549             """
       
   550             Returns the author name for every item in the feed.
       
   551             """
       
   552 
       
   553         item_author_name = 'Sally Smith' # Hard-coded author name.
       
   554 
       
   555         # ITEM AUTHOR E-MAIL --One of the following three is optional. The
       
   556         # framework looks for them in this order.
       
   557         #
       
   558         # If you specify this, you must specify item_author_name.
       
   559 
       
   560         def item_author_email(self, obj):
       
   561             """
       
   562             Takes an item, as returned by items(), and returns the item's
       
   563             author's e-mail as a normal Python string.
       
   564             """
       
   565 
       
   566         def item_author_email(self):
       
   567             """
       
   568             Returns the author e-mail for every item in the feed.
       
   569             """
       
   570 
       
   571         item_author_email = 'test@example.com' # Hard-coded author e-mail.
       
   572 
       
   573         # ITEM AUTHOR LINK --One of the following three is optional. The
       
   574         # framework looks for them in this order. In each case, the URL should
       
   575         # include the "http://" and domain name.
       
   576         #
       
   577         # If you specify this, you must specify item_author_name.
       
   578 
       
   579         def item_author_link(self, obj):
       
   580             """
       
   581             Takes an item, as returned by items(), and returns the item's
       
   582             author's URL as a normal Python string.
       
   583             """
       
   584 
       
   585         def item_author_link(self):
       
   586             """
       
   587             Returns the author URL for every item in the feed.
       
   588             """
       
   589 
       
   590         item_author_link = 'http://www.example.com/' # Hard-coded author URL.
       
   591 
       
   592         # ITEM ENCLOSURE URL -- One of these three is required if you're
       
   593         # publishing enclosures. The framework looks for them in this order.
       
   594 
       
   595         def item_enclosure_url(self, item):
       
   596             """
       
   597             Takes an item, as returned by items(), and returns the item's
       
   598             enclosure URL.
       
   599             """
       
   600 
       
   601         def item_enclosure_url(self):
       
   602             """
       
   603             Returns the enclosure URL for every item in the feed.
       
   604             """
       
   605 
       
   606         item_enclosure_url = "/foo/bar.mp3" # Hard-coded enclosure link.
       
   607 
       
   608         # ITEM ENCLOSURE LENGTH -- One of these three is required if you're
       
   609         # publishing enclosures. The framework looks for them in this order.
       
   610         # In each case, the returned value should be either an integer, or a
       
   611         # string representation of the integer, in bytes.
       
   612 
       
   613         def item_enclosure_length(self, item):
       
   614             """
       
   615             Takes an item, as returned by items(), and returns the item's
       
   616             enclosure length.
       
   617             """
       
   618 
       
   619         def item_enclosure_length(self):
       
   620             """
       
   621             Returns the enclosure length for every item in the feed.
       
   622             """
       
   623 
       
   624         item_enclosure_length = 32000 # Hard-coded enclosure length.
       
   625 
       
   626         # ITEM ENCLOSURE MIME TYPE -- One of these three is required if you're
       
   627         # publishing enclosures. The framework looks for them in this order.
       
   628 
       
   629         def item_enclosure_mime_type(self, item):
       
   630             """
       
   631             Takes an item, as returned by items(), and returns the item's
       
   632             enclosure mime type.
       
   633             """
       
   634 
       
   635         def item_enclosure_mime_type(self):
       
   636             """
       
   637             Returns the enclosure length, in bytes, for every item in the feed.
       
   638             """
       
   639 
       
   640         item_enclosure_mime_type = "audio/mpeg" # Hard-coded enclosure mime-type.
       
   641 
       
   642         # ITEM PUBDATE -- It's optional to use one of these three. This is a
       
   643         # hook that specifies how to get the pubdate for a given item.
       
   644         # In each case, the method/attribute should return a Python
       
   645         # datetime.datetime object.
       
   646 
       
   647         def item_pubdate(self, item):
       
   648             """
       
   649             Takes an item, as returned by items(), and returns the item's
       
   650             pubdate.
       
   651             """
       
   652 
       
   653         def item_pubdate(self):
       
   654             """
       
   655             Returns the pubdate for every item in the feed.
       
   656             """
       
   657 
       
   658         item_pubdate = datetime.datetime(2005, 5, 3) # Hard-coded pubdate.
       
   659 
       
   660         # ITEM CATEGORIES -- It's optional to use one of these three. This is
       
   661         # a hook that specifies how to get the list of categories for a given
       
   662         # item. In each case, the method/attribute should return an iterable
       
   663         # object that returns strings.
       
   664 
       
   665         def item_categories(self, item):
       
   666             """
       
   667             Takes an item, as returned by items(), and returns the item's
       
   668             categories.
       
   669             """
       
   670 
       
   671         def item_categories(self):
       
   672             """
       
   673             Returns the categories for every item in the feed.
       
   674             """
       
   675 
       
   676         item_categories = ("python", "django") # Hard-coded categories.
       
   677 
       
   678         # ITEM COPYRIGHT NOTICE (only applicable to Atom feeds) -- One of the
       
   679         # following three is optional. The framework looks for them in this
       
   680         # order.
       
   681 
       
   682         def item_copyright(self, obj):
       
   683             """
       
   684             Takes an item, as returned by items(), and returns the item's
       
   685             copyright notice as a normal Python string.
       
   686             """
       
   687 
       
   688         def item_copyright(self):
       
   689             """
       
   690             Returns the copyright notice for every item in the feed.
       
   691             """
       
   692 
       
   693         item_copyright = 'Copyright (c) 2007, Sally Smith' # Hard-coded copyright notice.
       
   694 
       
   695 
       
   696 The low-level framework
       
   697 =======================
       
   698 
       
   699 Behind the scenes, the high-level RSS framework uses a lower-level framework
       
   700 for generating feeds' XML. This framework lives in a single module:
       
   701 `django/utils/feedgenerator.py`_.
       
   702 
       
   703 Feel free to use this framework on your own, for lower-level tasks.
       
   704 
       
   705 The ``feedgenerator`` module contains a base class ``SyndicationFeed`` and
       
   706 several subclasses:
       
   707 
       
   708     * ``RssUserland091Feed``
       
   709     * ``Rss201rev2Feed``
       
   710     * ``Atom1Feed``
       
   711 
       
   712 Each of these three classes knows how to render a certain type of feed as XML.
       
   713 They share this interface:
       
   714 
       
   715 ``__init__(title, link, description, language=None, author_email=None,``
       
   716 ``author_name=None, author_link=None, subtitle=None, categories=None,``
       
   717 ``feed_url=None)``
       
   718 
       
   719 Initializes the feed with the given metadata, which applies to the entire feed
       
   720 (i.e., not just to a specific item in the feed).
       
   721 
       
   722 All parameters, if given, should be Unicode objects, except ``categories``,
       
   723 which should be a sequence of Unicode objects.
       
   724 
       
   725 ``add_item(title, link, description, author_email=None, author_name=None,``
       
   726 ``pubdate=None, comments=None, unique_id=None, enclosure=None, categories=())``
       
   727 
       
   728 Add an item to the feed with the given parameters. All parameters, if given,
       
   729 should be Unicode objects, except:
       
   730 
       
   731     * ``pubdate`` should be a `Python datetime object`_.
       
   732     * ``enclosure`` should be an instance of ``feedgenerator.Enclosure``.
       
   733     * ``categories`` should be a sequence of Unicode objects.
       
   734 
       
   735 ``write(outfile, encoding)``
       
   736 
       
   737 Outputs the feed in the given encoding to outfile, which is a file-like object.
       
   738 
       
   739 ``writeString(encoding)``
       
   740 
       
   741 Returns the feed as a string in the given encoding.
       
   742 
       
   743 Example usage
       
   744 -------------
       
   745 
       
   746 This example creates an Atom 1.0 feed and prints it to standard output::
       
   747 
       
   748     >>> from django.utils import feedgenerator
       
   749     >>> f = feedgenerator.Atom1Feed(
       
   750     ...     title=u"My Weblog",
       
   751     ...     link=u"http://www.example.com/",
       
   752     ...     description=u"In which I write about what I ate today.",
       
   753     ...     language=u"en")
       
   754     >>> f.add_item(title=u"Hot dog today",
       
   755     ...     link=u"http://www.example.com/entries/1/",
       
   756     ...     description=u"<p>Today I had a Vienna Beef hot dog. It was pink, plump and perfect.</p>")
       
   757     >>> print f.writeString('utf8')
       
   758     <?xml version="1.0" encoding="utf8"?>
       
   759     <feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><title>My Weblog</title>
       
   760     <link href="http://www.example.com/"></link><id>http://www.example.com/</id>
       
   761     <updated>Sat, 12 Nov 2005 00:28:43 -0000</updated><entry><title>Hot dog today</title>
       
   762     <link>http://www.example.com/entries/1/</link><id>tag:www.example.com/entries/1/</id>
       
   763     <summary type="html">&lt;p&gt;Today I had a Vienna Beef hot dog. It was pink, plump and perfect.&lt;/p&gt;</summary>
       
   764     </entry></feed>
       
   765 
       
   766 .. _django/utils/feedgenerator.py: http://code.djangoproject.com/browser/django/trunk/django/utils/feedgenerator.py
       
   767 .. _Python datetime object: http://www.python.org/doc/current/lib/module-datetime.html