Django RSS Feed Tutorial
Updated
Table of Contents
Django comes with a built-in syndication feed for dynamically generating RSS (Really Simple Syndication) or Atom feeds.
These feeds contain recently updated content on a website, and users can subscribe to them using a feed aggregator like Feedly. For example, this website's RSS feed is located at https://learndjango.com/feed/rss.
Adding a Django syndication feed takes only a few minutes. All we need to do is create a dedicated file—often called feeds.py
—that extends the built-in Feed class and then link it to a URL path. That's it!
Models, Views, URLs
For demonstration purposes, here are the models, views, and URLs for a tutorials app similar to what you see on this website. We'll use this as the basis for adding a feed in the next section.
The models file would look as follows:
# tutorials/models.py
from django.contrib.auth import get_user_model
from django.db import models
from django.urls import reverse
class Tutorial(models.Model):
author = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
title = models.CharField(max_length=200)
description = models.CharField(max_length=200)
slug = models.SlugField(null=False, unique=True)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
is_live = models.BooleanField(default=False)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('tutorial_detail', kwargs={'slug': self.slug})
class Meta:
ordering = ['-updated_at']
The views file would support a list page of all tutorials and a detail page for each.
# tutorials/views.py
from django.views.generic import ListView, DetailView
from .models import Tutorial
class TutorialListView(ListView):
model = Tutorial
context_object_name = 'tutorial_list'
template_name = 'tutorials/tutorial_list.html'
class TutorialDetailView(DetailView):
model = Tutorial
context_object_name = 'tutorial'
template_name = 'tutorials/tutorial_detail.html'
And the existing URLs path would look something like this:
# tutorials/urls.py
from django.urls import path
from .feeds import TutorialFeed
from .views import TutorialListView, TutorialDetailView
urlpatterns = [
path('<slug:slug>', TutorialDetailView.as_view(), name='tutorial_detail'),
path('', TutorialListView.as_view(), name='tutorial_list'),
]
Most websites have a similar pattern with a model, a view containing list and detail views, and two URL paths.
Feeds.py
To add RSS or Atom feeds to this app, we need to create a Feed class somewhere and add it to our URL. Doing this within a specific app might make sense if you want multiple feeds. However, if you intend to have one main feed for a project, adding it to the project-level directory is a good idea. That's what we'll do here.
The larger project for this Tutorials app is called django_project
. Therefore, we will create a new file called django_project/feeds.py
in the project-level directory. Here are the contents of the file:
# django_project/feeds.py
from django.contrib.syndication.views import Feed
from django.template.defaultfilters import truncatewords
from tutorials.models import Tutorial
class RssTutorialsFeeds(Feed):
title = "Tutorials"
link = "/latesttutorials/"
description = "Recent free tutorials on LearnDjango.com."
def items(self):
return Tutorial.objects.order_by("-updated_at")[:100]
def item_title(self, item):
return item.title
def item_description(self, item):
return truncatewords(item.content, 30)
def item_lastupdated(self, item):
return item.updated_at
This Feeds file starts by importing the Feed class and the template filter truncatewords at the top. Next, we also import the Tutorial
model from the tutorials
app.
We define our custom feed by subclassing the Feed
class and providing a name, RssTutorialsFeeds
here. The title
, link
, and description
are required RSS elements.
The meat of the feed is the following three methods:
items
retrieves the objects for the feed; in this case the last 100 sorted byupdated_at
.item_title
returns thetitle
item_description
returns thedescription
truncated to 30 wordsitem_lastupdated
returns theupdated_at
timestamp
URLS.py
The second step is to create a URL path for the feed in the project-level urls.py
file. We need to import our custom feed class, RssTutorialsFeeds
, and provide it a new URL pattern.
# django_project/urls.py
from django.contrib import admin
from django.urls import path, include
from .feeds import RssTutorialsFeeds # new
urlpatterns = [
path('admin/', admin.site.urls),
path('tutorials/', include('tutorials.urls')),
path('feed/rss', RssTutorialsFeeds(), name="tutorial_feed"), # new
]
Navigate to http://127.0.0.1:8000/feed/rss
in your web browser, and the RSS feed will list all included tutorials (make sure you have added some to your admin for this example to work!).
In Chrome, you will see the XML code for the RSS feed directly, and in Safari, it will ask you to install an RSS feed reader. The free Fluent app is a good choice and supports Linux, macOS, and Windows.
Navbar
The last step is notifying your users about the RSS feed somehow, usually in the header or footer of your website. You can use the named URL, tutorial_feed
, to do this. Something like the below:
<a href="{% url 'tutorial_feed' %}">RSS Feed</a>
Atom
Django allows you to publish either an RSS feed, an Atom feed, or both. To add Atom, we can subclass RssTutorialsFeeds
to something different.
# django_project/feeds.py
from django.contrib.syndication.views import Feed
from django.template.defaultfilters import truncatewords
from django.utils.feedgenerator import Atom1Feed # new
from tutorials.models import Tutorial
class RssTutorialsFeeds(Feed):
title = "Tutorials"
link = "/latesttutorials/"
description = "Recent free tutorials on LearnDjango.com."
def items(self):
return Tutorial.objects.order_by("-updated_at")[:100]
def item_title(self, item):
return item.title
def item_description(self, item):
return truncatewords(item.content, 30)
def item_lastupdated(self, item):
return item.updated_at
class AtomSiteNewsFeed(RssTutorialsFeeds): # new
feed_type = Atom1Feed
subtitle = RssTutorialsFeeds.description
Then we update the URLconf.
# django_project/urls.py
from django.contrib import admin
from django.urls import path, include
from .feeds import RssTutorialsFeeds # new
urlpatterns = [
path('admin/', admin.site.urls),
path('tutorials/', include('tutorials.urls')),
path('feed/atom', RssTutorialsFeeds(), name="tutorial_feed"), # new
]
In your web browser, navigate to http://127.0.0.1:8000/feed/atom
to see the Atom feed.
Next Steps
As a batteries-included web framework, Django comes with many built-in features to help. For example, you can add a dynamically-generated sitemap. And if you want to add a favicon to your project, here is a Django Favicon tutorial to help.