Create your RSS/Atom feed in Wagtail

See how to create your own RSS/Atom feed in your Wagtail site fast and easy.

Date and Time of last update Wed 24 Jun 2020
  


A good suggestion to add support for RSS/Atom to erev0s.com was made by a fellow reader. Given that I had not considered it so far, since I actually never use it, I started searching on what is already available for Django and Wagtail. Once again the developers behind Django had made sure to cover that aspect super well! Looking for something specific to wagtail I found two options, the Django Wagtail Feeds and the snotra_rss. After inspecting both, I saw that the first has not received any update for more than two years and the second was doing much more than what I needed while my intention was to keep things simple. So this brought me to the decision to actually make it on my own, after all Django developers made sure that there is not much to do anyway! You can access the result for RSS here and for Atom here.


Ok so without further ado, lets dive into the implementation details.

The Django documentation about RSS is pretty clear and can be found here. It is very well written and If you have time make sure you give it a read.

The first thing in our list is to create a python file inside our app. In this case the file feeds.py is created.

The contents of that file are shown below

from django.contrib.syndication.views import Feed
from blog.models import BlogPage
from django.utils.feedgenerator import Atom1Feed


class RssFeed(Feed):
    title = "erev0s.com personal blog page"
    link = "/"
    description = "A blog about cyber security, web development and other tech related topics"
    feed_url = '/rss/'
    author_name = 'erev0s'
    categories = ("python", "django", "cyber security", "android", "hacking")
    feed_copyright = 'Copyright (c) 2019-2020, erev0s.com'

    language = 'en'

    def items(self):
        return BlogPage.objects.order_by('-date')[:5]

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

    # return a short description of article
    def item_description(self, item):
        return item.intro

    # return the URL of the article
    def item_link(self, item):
        return item.full_url

    # return the date the article was published
    def item_pubdate(self, item):
        return item.first_published_at

    # return the date of the last update of the article
    def item_updateddate(self, item):
        return item.last_published_at

    # return the categories of the article
    def item_categories(self, item):
        return item.categories.all()


class AtomFeed(RssFeed):
    feed_type = Atom1Feed
    link = "/atom/"
    subtitle = RssFeed.description


There are two classes the RssFeed and the AtomFeed. The AtomFeed has exactly the same things as the RssFeed, their difference is the feed_type, the link and the subtitle. The feed_type is simple which kind of feed we are using, you can see the available types here, the link is just where the feed is located in the site and the subtitle is a specific to Atom thing that does not exist in RSS.

The contents of the RssFeed are self-explanatory so we are not going to go through them. Basically on top you have details about the website and the author and below details about each article (item).

Our next step and final step is to adjust our urls.py file to include these two classes into the appropriate urls. The following snippet shows the two lines of interest:

...
from blog.feeds import RssFeed, AtomFeed

urlpatterns = [
...
    url(r'rss/', RssFeed(), name='rssfeed'),
    url(r'atom/', AtomFeed(), name='atomfeed'),
...
]


That is it, we can now visit our site on the /rss and /atom urls and the corresponding feeds will be available.


Images in RSS/Atom

You might question why we did not add an image to our feeds, well I wanted to keep things as simple as possible, maybe I will add it in the future. Though, in case you would like to add an image as well to your feed, the following snippet will do the job.

def item_description(self, item):
    return '<![CDATA[\n{} <img src="{}" alt="{}">\n]>'.format(item.intro, item.imageURL, item.image-alt)

Keep in mind that you have to adjust the item.imageURL to retrieve the correct image URL for each case. An example on how you could do that is using myimage.get_rendition('fill-300x186|jpegquality-60').url. There are other ways as well but I believe using CDATA is a clean way it can be done. Feel free to try out other methods as described in this stackoverflow post.


Conclusion

In this article we saw how to add RSS and Atom feeds to a Wagtail website and how to customize them with the details we want to include. Make sure you validate your feeds after creation with this tool provided by W3.org.