SaltyCrane Blog — Notes on JavaScript and web development

Django Blog Project #7: Adding a simple Atom feed

Setting up a basic Atom feed for my new blog was not too difficult. I followed the instructions in the Django documentation and created a basic Atom feed for my 10 latest posts. There were a couple of things I couldn't figure out: 1) how to create a feed for a specific tag, and 2) how to redirect my feed to FeedBurner. I know these things are not that hard, but I want to get my new blog working as soon as possible so I can start using it. If anyone knows how to do these things, I'd be grateful for your feedback. Regarding item 1, I plan to replace my tagging functionality hack with the django-tagging application so maybe I will wait until then to add tag-specific feeds. Regarding item 2, I read about using .htaccess to do redirects, but I couldn't figure out how to do a feed redirect at Webfaction.

Anyways, here are the steps I took to create a basic feed of my latests posts. Refer to the Django syndication feed framework documentation for more details.



Modify the URLConf
Per the documentation, I modified my ~/src/django/myblogsite/urls.py:
from django.conf.urls.defaults import *
from iwiwdsmi.myblogapp.views import *
from iwiwdsmi.feeds import *

feeds = {
    'latest': LatestPosts,
}

urlpatterns = patterns(
    '',
    (r'^site_media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': '/home/sofeng/src/django/myblogsite/media'}),

    (r'^admin/', include('django.contrib.admin.urls')),
    (r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed', 
     {'feed_dict': feeds}),    
    
    (r'^blog/$', frontpage),
    (r'^blog/(\d{4,4})/(\d{2,2})/([\w\-]+)/$', singlepost),
    (r'^blog/(\d{4,4})/$', yearview),
    (r'^blog/(\d{4,4})/(\d{2,2})/$', monthview),
    (r'^blog/tag/([\w\-]+)/$', tagview),
)


Create a feeds.py file

I created the following file at ~/src/django/myblogsite/feeds.py. Note, I factored out my main title, "Sofeng's Blog 0.0.6", into the variable MAIN_TITLE in my views.py file and used it here. The class attributes, title and description are strings describing the feed.

from django.contrib.syndication.feeds import Feed
from django.utils.feedgenerator import Atom1Feed
from iwiwdsmi.myblogapp.models import Post
from iwiwdsmi.myblogapp.views import MAIN_TITLE

class LatestPosts(Feed):
    title = MAIN_TITLE
    link = "/blog/"
    description = MAIN_TITLE + ": Latest posts"
    feed_type = Atom1Feed
    
    def items(self):
        return Post.objects.order_by('-date_created')[:10]


Create feed templates

I created two feed templates which are used to display the title and body for each post. They each only contain one line.

~/src/django/myblogsite/templates/feeds/latest_title.html:
{{ obj.title }}

~/src/django/myblogsite/templates/feeds/latest_description.html:
{{ obj.body }}


Display a link to the new feed

I added a link to my new feed in my base.html template.

Excerpt from ~/src/django/myblogsite/templates/base.html:
        <h4>FEEDS</h4>
          <a href="/feeds/latest/" rel="alternate" type="application/rss+xml"><img alt="" style="vertical-align:middle;border:0" src="http://www.feedburner.com/fb/images/pub/feed-icon16x16.png"/></a>
        <a href="/feeds/latest/">Subscribe to Atom feed</a><br>


Change site name

When I first created my Django project, I installed the django.contrib.sites app (by default), but I did not change my site name, so my feed used the site example.com instead of my real site. Here is how I changed my site name:

  1. I went to the admin page at http://127.0.0.1:8000/admin/
  2. I clicked on "Sites", then on "example.com".
  3. I changed "example.com" to "saltycrane.com" and clicked the "Save" button.


Deploy and Test

I pushed my changes to the Webfaction server, updated my repository, and restarted the Apache server. Then I pointed Firefox at http://saltycrane.com/blog/ and clicked on my new "Subscribe to Atom feed" link. I subscribed to the feed using "Google" and chose "Add to Google Reader" and saw my new feed in Google Reader.
Here is a screenshot of my feed in my Google Reader:


Extra links on redirection for my reference:
Webfaction knowledgebase article on redirection
Blog article on redirecting feeds to FeedBurner

Related posts:
  Django Blog Project #1: Creating a basic blog
  Django Blog Project #2: Deploying at Webfaction
  Django Blog Project #3: Using CSS and Template Inheritance
  Django Blog Project #4: Adding post metadata
  Django Blog Project #5: YUI CSS and serving static media
  Django Blog Project #6: Creating standard blog views
  Django Blog Project #8: Adding basic comment functionality with Django Free Comments

Comments


#1 defermat commented on :

So I was trying out your latest addition to your blog -- RSS feeds. However I keep getting this error whenever I add the feeds URL specifier as you specified:

('^feeds/(?P*)/$', 'django.contrib.syndication.views.feed', {'feed_dict': feeds}),

and the error:

ImproperlyConfigured at /feeds/latest/
Error while importing URLconf 'blog.urls': unknown specifier: ?P*

any hints on the cause of this? I haven't been able to find any thing on the django forums or anywhere else, so any help would be greatly appreciated!

Also, I've reconstructed your entire blog tutorials up to this point for learning purposes, and everything else works as expected.


#2 defermat commented on :

I realized I copied the line of code and error from a deviation of your code.

Again with the correct code:

('^feeds/(?P.*)/$', 'django.contrib.syndication.views.feed', {'feed_dict': feeds}),

and the error:

ImproperlyConfigured at /feeds/latest/
Error while importing URLconf 'blog.urls': unknown specifier: ?P.


#3 sofeng commented on :

defermat,
I'm sorry-- I forgot to escape the < and > characters for that code snippet. The line should read:

(r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed',   
 {'feed_dict': feeds}),

Sorry about that. I fixed it in the post.


#4 defermat commented on :

great. thanks!


#5 johnson commented on :

Dear Sir

I want to know how to write a (r'^admin/', include('django.contrib.admin.urls')), code for views py

help me to clear this error

Johnson