Adding an RSS feed to a Wagtail site

March 4, 2016

First of all, it's exactly how you would do it in a normal Django-powered site. The official docs for creating RSS or Atom feeds can be found here. That's one of the beauties of Wagtail, it keeps hold of many of the great features of Django.

But if you're not too familiar with Django, or the commonalities between vanilla Django and Wagtail, then hopefully this description of how I implemented an RSS feed on this site will help you.

There are two elements to an RSS feed in Django/Wagtail:

  1. The Feed class
  2. The URL configuration

Writing the Feed class

The Feed class gets all the relevant bits of data needed to serve the RSS feed to the client. It's essentially a class-based view.

The code for this can live anywhere within your codebase. I chose to create a new app for it. To do this I created a new folder in the root of my Wagtail project, called 'blog_feed' (it could be called whatever you want). Within this are two files:

I then added the app 'blog_feed' to the INSTALLED_APPS section of my base.py settings file.

With that done, back to the forms.py file. Below you can see the final code for my first RSS feed:

from django.db import models
from django.contrib.syndication.views import Feed
from blog.models import BlogPage

class BlogsFeed(Feed):
    title = "My blog articles"
    link = "/blogs-feed/"
    description = "All of my blogs as they are published"

    def items(self):
        return BlogPage.objects.live().order_by('-date')

    def item_title(self, item):
        return item.title

    def item_description(self, item):
        return item.intro

In our first three lines we import the essential elements needed to create our Feed class. It will inherit the functionality of the basic Django Feed class, so we import that. 

We also import the BlogPage model so that we can access the URLs, titles and descriptions that will make up the feed itself.

Then we create the class itself. As you can see in the first line, we subclass django.contrib.syndication.views.Feed by including it in the class definition.

class BlogsFeed(Feed):

The next three lines define the standard title, link and description values that begin all RSS feeds. You can see them in the output at chrxr.com/blog-feed. These are required!

<title>My blog articles</title>
<link>https://chrxr.com/blogs-feed/</link>
<description>All of my blogs as they are published</description>

Following that we define three standard methods for our Feed class. Again, all four of these are required to provide all the information necessary to build the feed.

The first method, items, gets the objects (pages) which we're going to list in the RSS feed from the database.

    def items(self):
        return BlogPage.objects.live().order_by('-date')

The next two methods retrieve specific field information from each individual object. The first is populating the title for the link in the RSS feed. Usually this will be self.title, but it might be self.seo_title, or you may have another field on your blog model that you want to use.

The second method gets the description to go along with the link. This is more open to interpretation. I've used the self.intro field as it is often populated.

    def item_title(self, item):
        return item.title

    def item_description(self, item):
        return item.intro

Defining the links

There's one final ingredient missing from this RSS pie, the actual links to the articles. Django's Feeds module has the power to extract these links itself, but only if the model listed in the RSS feed has a get_absolute_url() method.

This isn't a big problem though. I simply added the following line to my BlogPost model:

    def get_absolute_url(self):
        return self.full_url

And that's it! The code for generating the feed is complete. Now onto the task of defining a URL to access the feed.

Adding the RSS feed URL

This bit is easy. You simply import your Feed class into the urls.py file,  then add the line below to the urlpatterns section.

from blog_feed.feeds import BlogsFeed

urlpatterns = [
    #.... lots of URLs

    url(r'blog-feed/$', BlogsFeed()),

   # .... more URLs
]

So, when someone visits the URL http://chrxr.com/blog-feed, Wagtail initialises a new instance of the class BlogFeed, which responds to the browser with the feed of links defined in the class methods.

If you have an RSS browser extension installed (like me), this might display the links in the feed as a nice list. If not you'll likely just see a load of XML. Generally though, as long as you don't see an error, then it's working!

Screenshot of RSS feed with Chrome extension

See it on GitHub

This blog uses GitHub for version control, so the source code for anything I mention can generally be found there.