Current Twitter Status

See status in context

Subsidized Fear

Terror Alert Level

Blog Entries Tagged With “rss” (Show All Items Tagged With “rss”)

Fun With Django Feeds

Posted on Friday, August 3, 2007 @ 02:04 CDT by Daniel Andrlik

I would like to take a moment to show you how easy it is to create feeds in Django, and the easiest way to do that is by example. For brevity’s sake, I’m going to use a simplified version of a Django-powered blog. So, let’s say you have a simple blog, where posts consist of a title, slug, pub_date, body and some tags. So your model would look something like this:

blog/models.py

from django.db import models
from tag.fields import TagField
from datetime import datetime

class Entry(models.Model):
    title = models.CharField(maxlength=250)
    slug = models.SlugField(
                 maxlength=250,
                 prepopulate_from=('title'),
                 unique_for_date='pub_date'
    )
    body = models.TextField()
    pub_date = models.DateTimeField(default=datetime.now())
    is_draft = models.BooleanField(default=True)
    allow_comments = models.BooleanField(default=True)
    tags = TagField()
    
    def __unicode__(self):
        return self.title
    
    def get_absolute_url(self):
        #You would fill this in here and call it when you need it or 
        #use the permalink decorator
        #Regardless, you want to customize it for your urls.py
        pass

Now, I’m assuming you already know something about the Django ORM, but I’ll summarize for those of you that don’t. Essentially, we are creating an object of type Entry, which represents a table in your database and has the attributes I listed above. I’ve added a few constraints, such as requiring the slug field to be unique for a given date, since in most cases you will probably build a permalink along the lines of /year/month/day/slug. I’ve also cheated and added two boolean fields which designate if the entry is a draft, and if it allows comments, because they are too useful to leave out, even in an example. TagField is supplied by the django-tagging app, and doesn’t really affect the rest of this example, but I love it so I’m going to leave it in. ;-)

Okay, so you’ve got your model and you have used it to load up some entries, and now it suddenly occurs to you: What’s a blog without a subscription feed? The answer to that question is: Probably not worth the effort to remember visiting on a regular basis. You need an RSS feed! Luckily for you, Django makes this dead simple.

So, the first order of business is to define a feed class to represent your data. Unless you have very complex needs, this is very simple because you just have to subclass the Feed class in Django. You’ll have to define a few variables and then tell the feed what items it should be displaying and what date is the representative pubdate. So, a simple example might look like this:

feeds.py

from django.contrib.syndication.feeds import Feed
from blog.models import Entry

class BlogFeed(Feed):
    '''Feed for latest 15 blog entries'''
    #These could also be pulled from your settings.py file to avoid repetitive hardcoding
    title='My Blog'
    link='http://www.example.com' #URI of site
    description='Latest Blog Entries'
    
    item_author_name='Joe Blow'
    item_author_email='joe@example.com'
    item_author_link='http://www.example.com' #URI of author
    
    def items(self):
        #What items to use in the feed
        return Entry.objects.filter(is_draft=False).order_by('-pub_date')[:15]
    
    def item_pubdate(self,item):
        #For each item, what is the pubdate?
        return item.pub_date

So, that’s a simple feed. Now you need to assign this feed to a url, which you do by adding it to your urls.py file. I’m going to just include the feed urls line rather than including an entire site description.

urls.py

from django.conf.urls.defaults import *
from feeds import *

#Here you add a dictionary of feeds with a slug you want them to correspond to

site_feeds = {
        'blog':BlogFeed
}

urlpatterns = patterns('',
  #Lots of patterns omitted here
  (r'^feeds/(?P< url >.*)/$', 'django.contrib.syndication.views.feed',{'feed_dict':site_feeds}),
)

This tells Django that for every time it encounters a request beginning with feeds, it should take the remainder of the url as a slug and find the corresponding feed class in site_feeds. There is only one step left, making the templates. Don’t worry, this is the easiest part.

Every feed needs two templates, although you can reuse templates by specifying the title_template and description_template in your feed class. Otherwise, Django will look for templates that match your feed’s slug identifier in the templates/feeds directory, where templates is your base directory for templates. In this case it will be looking for blog_title.html and blog_description.html. Both templates get passed one variable: obj, which represents a single item in the feed. Both are ridculously simple:

blog_title.html

{{ obj.title }}

blog_description.html

{{ obj.body }}

They are really that simple. You can, of course, apply all your favorite Django template filters or add extra formatting if you wish. If you want to include any other information that you might pull via template tags, you can use those as well. For example if you wanted to also include a comment count your description template would look like this:

blog_description.html

{% load comments %}
{% get_comment_count for blog.entry obj.id as comment_count %}
{{ obj.body }}
{{ comment_count }} comment{{ comment_count|pluralize }} on this entry.

By default, Django will serve up your feed as RSS 2.0, however, you can also create Atom feeds just as easily. You can even serve up both types of feeds by subclassing your BlogFeed class like so:

feeds.py

from django.contrib.syndication.feeds import Feed
from blog.models import Entry
from django.utils.feedgenerator import Atom1Feed

#For brevity's sake, I'm omitting the BlogFeed I described above.

class AtomBlogFeed(BlogFeed):
    feed_type = Atom1Feed
    subtitle = BlogFeed.description

That’s all there is to it! Simply assign it a feed slug and either create new templates or specify in the AtomBlogFeed class to use the same templates as BlogFeed.

It is possible to completely customize your feeds, but that’s a little out of the scope of this post. This basic approach should work for the majority of cases, and if you need to do something more advanced with your feed, take a moment to browse through the official documentation as there are a wealth of options available to you.

This may initially look like a lot of work, but believe me this takes no time at all. This site generates feeds for every kind of content, including by tag, and tag per category, and I was able to write all of those feeds and have them being served up in about twenty minutes. For a simple example like I am showing here you can be up with feeds in less than ten!

Django makes feed generation quick and easy, and like most aspects of Django, is a joy to work with. Go ahead, take a moment and play with it. If you need an app to work with, you can either flesh out this example or you can go through the official tutorial. Afterwards, I’m pretty sure you’ll be hooked. ;-)

Checking Out Google Reader

Posted on Monday, January 29, 2007 @ 21:18 CST by Daniel Andrlik

On recommendation of far too many people to mention, I’m checking out Google Reader again.

I remember peeking at it when it was first released, when I was stubbornly intent on sticking with browser/desktop based reader, and I remember being less than impressed. In typical Google fashion the initial interface was so sparse and ultimately gave me the initial impression of it being a fairly weak client. In fact, I was so turned off by it, that I never gave it a chance beyond feeding it a few test subscriptions before going back to using Sage.

Ultimately, it would be Bloglines that converted me to web-based feed reading. I fell in love with its simple interface and powerful key commands, as well as the convenience of accessing my feeds everywhere. As I began to imbibe more and more of the Web 2.0 kool-aid, I began to manage more and more of my life on the web. I’ve been using Bloglines for at least nine months now, and I’ve been quite happy with it. The Bloglines notifier held a place of honor in my Firefox status bar, right next to theGmail manager extension.

bloglines

Now, when I started hearing people recommending Google Reader to me again, I was suspicious that the Google fanboy virus was to blame. However, upon reflecting on the wonder that is Gmail, not to mention Google Calendar and the fantastic overhaul of Google Groups I decided that I’d give Reader another try.

All I have to say is, “Wow.” I’m really impressed with the new interface, it seems to blend the best features of Bloglines, Gmail and more tag-based service like Rojo. The key-commands are similar to Gmail, and uses tags/labels just like Gmail as well. The interface is really nice and I find the interface far more visually pleasing than Bloglines, and not nearly as cluttered as Rojo. I like that when I start reading a feed that items are marked as read when I scroll past them, as opposed to Bloglines which marks every item as read as soon as I open the feed. Also, while I don’t make use of this feature as much, I really like the way Google integrates their feed sharing features into the service. Every feed has the option to be shared, as does each feed item, and each feed item can be emailed with a single click. Very slick.

google reader

Those sharing features are also available in Bloglines, but they seem more prominent in Google Reader. On the whole, GR seems more polished, although I do enjoy the simplicity of Bloglines. It remains to be seen if I’m going to switch for good, but I think I’ll run them both parallel for a while and let you all know about the experience.

Incidentally, if you want to try out Google Reader, I’d recommend checking out the Google Reader Notifier extension for Firefox, by Mark D.B.D. It rocks.