Working With Django and RSS Feeds

Sept. 17, 2012, 10:42 p.m.

Yesterday, I added a new feature to the site, an RSS feed of my blog. This feature was really easy to implement thanks to Django. Django comes with an RSS feed function which consists of a class:

from django.contrib.syndication.views import Feed

which you use to subclass with your Feed class. When you do this, it allows you to inject defined content and then Django will construct the RSS feed consisting of the given information. For more details on the ins-and-outs of the syndication feed framework visit the django documentation.

What this post is assuming is that you have already become familiar with how the syndication feed framework works and you are looking to begin creating your RSS feed with the Feed subclass.

Getting Started

I first created a django app called "feeds", the reason I did this was because you need a place to store the feeds.py file and this was the best solution in my opinion.

I then created my Feeds subclass file called "feeds.py" and placed it into my feeds app folder.

Here is what my feeds.py file consists off:

// Importing the syndication feed and my Article class from my blog model.
from django.contrib.syndication.views import Feed
from blog.models import Article

class BlogFeed(Feed):
    // Here I am setting the default RSS information that gets shown at the top of the feed.
    title = "ZachRohde.com"
    link = "/blog/"    // See the last portion of this post for information on this part
    description = "Recent Blog Entries on ZachRohde.com"
    
    // These are my "hard-coded" author information.
    author_email = 'zach@zachrohde.com'
    author_link = 'http://zachrohde.com'
    
    // Here I am pointing to my custom templates for the blog title and blog description, I will talk about these in a little.
    title_template = '_feeds/blog_title.html'
    description_template = '_feeds/blog_description.html'
    
    // This pulls the blog.model's charfield "author" so that the author's name can be dynamic (I just did this to future proof).
    def item_author_name(self, item):
        return item.author
    
    def items(self):
        return Article.objects.filter(enabled=True).order_by('-created')[:10]

    // This pulls the blog.model's datefield "created" which just shows when the blog post was made.
    def item_pubdate(self, item):
        return item.created

Now you are probably wondering what that title_template and title_description stuff was, now I will tell you! So Django allows you to customize the look and feel of the RSS feed by just simply creating a couple templates. I will go into more detail when I show the two below.

Here is my blog_template file:

// I currently have no customizations on the title, so it just simply outputs the blog.model's charfield "title" which contains the blog posts' title.
{{ obj.title }}

Here is my blog_description file:

// Since I have no "summary" field or the like in my blog model I just simply truncate the blog posts' content to create a summary (which is why I needed to customize the RSS feed!)
{% autoescape off %}
{{ obj.body|truncatewords_html:60 }}
{% endautoescape %}

// Here I am displaying the current comment count for the article.
<a title="View comments for: {{ obj.title }}" href="{{ obj.get_absolute_url }}/#comments">[{{ article.comments|length }}] {% if article.comments|length == 1 %}Comment{% else %}Comments{% endif %}</a>

Now you need to add a one little statement in your main url.py file:

// Importing the usual and importing the BlogFeed Feed class (very important!)
from django.conf.urls import patterns, include, url
from feeds.feed import BlogFeed

urlpatterns = patterns('',
    // I cut out the other URL stuff...
    
    // Here I am creating the URL and putting in an instance of the feed object.
    url(r'^feeds/blog/$', BlogFeed()),
)

And that's it! You are done! You have just created your first Django powered RSS feed which with the template trick, will allow you to customize the content it pulls. Now if you are having troubles with the URL stuff, the following might help you.

So I was running into the issue where I couldn't get the contents of "link" (inside feed.py) to populate correctly. "Link" is where Django tries getting the associated blog post link for each article, so you have to do a couple of things to get that to work.

Additional Issues

The first thing you need to do if you have not already added this to your blog's model is to define an absolute URL:

// This goes inside your blog.model or the like...
@models.permalink
def get_absolute_url(self):
    return ('blog.views.article', (), {
        'year': self.created.year,
        'month': self.created.strftime('%m'),
        'slug': self.slug})

Once you have that, Django can then execute

get_absolute_url()

on the object and it will return with the exact URL. Then inside your feed.py file, just have the starting URL for the link value, for example mine is /blog/ because it is zachrohde.com/blog/2012...

I hope that this little tutorial was useful to those of you having a bit of troubles. Leave a comment if you have any questions or concerns!