Ticket #6304: single_feed.diff
File single_feed.diff, 7.0 KB (added by , 17 years ago) |
---|
-
django/contrib/syndication/views.py
1 1 from django.contrib.syndication import feeds 2 2 from django.http import HttpResponse, Http404 3 3 4 def feed(request, url, feed_dict=None):4 def multiple_feeds(request, url, feed_dict=None): 5 5 if not feed_dict: 6 raise Http404 , "No feeds are registered."6 raise Http404("No feeds are registered.") 7 7 8 url_params = url.split('/') 8 9 try: 9 slug, param = url.split('/', 1)10 except ValueError:11 slug, param = url, ''10 slug, rest = url_params[0], url_params[1:] 11 except IndexError: 12 raise Http404("Slug not provided.") 12 13 13 14 try: 14 f = feed_dict[slug]15 feed_class = feed_dict[slug] 15 16 except KeyError: 16 raise Http404 , "Slug %r isn't registered." % slug17 raise Http404("Slug %r isn't registered." % slug) 17 18 19 return single_feed(request, slug, *rest, **{'feed_class': feed_class}) 20 21 # This function used to be called feed(). Keep this alias for backwards 22 # compatibility. 23 feed = multiple_feeds 24 25 def single_feed(request, slug, *url_args, **url_kwargs): 18 26 try: 19 feedgen = f(slug, request).get_feed(param) 27 feed_class = url_kwargs.pop('feed_class') 28 except KeyError: 29 raise ValueError('single_feed() requires a `feed_class` keyword argument') 30 if url_kwargs: 31 raise ValueError('single_feed() got unknown keyword argument(s): %s' % ', '.join(url_kwargs.keys())) 32 try: 33 feedgen = feed_class(slug, request).get_feed(url_args) 20 34 except feeds.FeedDoesNotExist: 21 raise Http404, "Invalid feed parameters. Slug %r is valid, but other parameters, or lack thereof, are not." % slug 22 35 raise Http404("Invalid feed parameters: %r" % (url_args,)) 23 36 response = HttpResponse(mimetype=feedgen.mime_type) 24 37 feedgen.write(response, 'utf-8') 25 38 return response -
django/contrib/syndication/feeds.py
55 55 return attr() 56 56 return attr 57 57 58 def get_feed(self, url =None):58 def get_feed(self, url_params): 59 59 """ 60 60 Returns a feedgenerator.DefaultFeed object, fully populated, for 61 61 this feed. Raises FeedDoesNotExist for invalid parameters. 62 62 """ 63 if url: 63 # url_params is a list of captured parameters (as strings) from the 64 # URLconf. It can be empty. 65 if url_params: 64 66 try: 65 obj = self.get_object(url .split('/'))67 obj = self.get_object(url_params) 66 68 except (AttributeError, ObjectDoesNotExist): 67 69 raise FeedDoesNotExist 68 70 else: -
docs/syndication_feeds.txt
40 40 To activate syndication feeds on your Django site, add this line to your 41 41 URLconf_:: 42 42 43 (r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views. feed', {'feed_dict': feeds}),43 (r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.multiple_feeds', {'feed_dict': feeds}), 44 44 45 45 This tells Django to use the RSS framework to handle all URLs starting with 46 46 ``"feeds/"``. (You can change that ``"feeds/"`` prefix to fit your own needs.) 47 47 48 (Note that this ``multiple_feeds`` view used to be called ``feed``, but it's 49 been renamed in the Django development version to be clearer, and to allow for 50 other feed views, such as ``single_feed()``, which is explained below. However, 51 if your code refers to the ``feed`` view, it will still work.) 52 48 53 This URLconf line has an extra argument: ``{'feed_dict': feeds}``. Use this 49 54 extra argument to pass the syndication framework the feeds that should be 50 55 published under that URL. … … 65 70 66 71 urlpatterns = patterns('', 67 72 # ... 68 (r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views. feed',73 (r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.multiple_feeds', 69 74 {'feed_dict': feeds}), 70 75 # ... 71 76 ) … … 377 382 378 383 urlpatterns = patterns('', 379 384 # ... 380 (r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views. feed',385 (r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.multiple_feeds', 381 386 {'feed_dict': feeds}), 382 387 # ... 383 388 ) … … 786 791 787 792 item_copyright = 'Copyright (c) 2007, Sally Smith' # Hard-coded copyright notice. 788 793 794 The ``single_feed()`` view 795 -------------------------- 789 796 797 **New in Django development version** 798 799 Above, we explained that your URLconf should point at the ``multiple_feeds()`` 800 view, like so:: 801 802 (r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.multiple_feeds', {'feed_dict': feeds}), 803 804 However, as explained above, the ``multiple_feeds()`` view makes a few 805 assumptions that may not be appropriate for your particular setup. Specifically: 806 807 * It assumes you have multiple feeds. It's overkill to have to define a 808 ``feed_dict`` if you only have a single feed. 809 810 * It uses very simple URL parsing -- the captured value of ``url`` is 811 simply split by the slash character (``'/'``) and passed to 812 ``Feed.get_object()``. This is slightly inconvenient in that it requires 813 your ``Feed`` class to handle URL parsing. 814 815 As an alternative to the ``multiple_feeds()`` view, Django provides a 816 ``single_feed()`` view. The difference here is that ``single_feed()`` only 817 applies to a single ``Feed`` class (as opposed to a ``feed_dict``), and it 818 accepts captured URL arguments, which means you can keep your URL-parsing 819 logic in your URLconf. 820 821 For example, consider the chicagocrime.org "per-beat" feed explained above. 822 Recall the per-beat feeds, with URLs like this: 823 824 * ``/rss/beats/0613/`` -- Returns recent crimes for beat 0613. 825 * ``/rss/beats/1424/`` -- Returns recent crimes for beat 1424. 826 827 In the implementation above, the URL parsing was handled in 828 ``BeatFeed.get_object()``. But using ``single_feed()``, we can implement the 829 URL parsing in the URLconf, like this:: 830 831 (r'^feeds/(beats)/(\d\d\d\d)/$', 'django.contrib.syndication.views.multiple_feeds', 832 {'feed_class': feeds.BlockFeed}), 833 834 Then, with the URL parsing taken care of by the URLconf, 835 ``BeatFeed.get_object()`` no longer has to parse a string. Instead, it's passed 836 a list of parameters captured from the URL:: 837 838 class BeatFeed(Feed): 839 def get_object(self, bits): 840 return Beat.objects.get(beat__exact=bits[0]) 841 842 Note that, unlike the ``single_feed()`` implementation of 843 ``BeatFeed.get_object()``, here we don't have to worry about checking for a 844 wacky URL such as ``"/rss/beats/0613/foo/bar/baz/"``, because that will have 845 been caught by the URLconf. 846 790 847 The low-level framework 791 848 ======================= 792 849