Creating Feeds with Django

Django ships with built-in syndication feed generating framework, which is used to generate dynamic Atom and RSS feeds.

RSS is an abbreviation for Really Simple Syndication, it’s a way to have information delivered to you instead of you having to go find it. RSS is basically a structured XML document that includes full or summarized text along with other metadata such as published date, author name, etc.

Creating RSS Feeds with Django

In this article, we are going to generate feeds for a blog application following is the models.py file.

class Post(models.Model):
    title = models.CharField(max_length=200, unique=True)
    slug = models.SlugField(max_length=200, unique=True)
    author = models.ForeignKey(
        User, on_delete=models.CASCADE, related_name="blog_posts"
    )
    updated_on = models.DateTimeField(auto_now=True)
    content = models.TextField()
    created_on = models.DateTimeField(auto_now_add=True)
    status = models.IntegerField(choices=STATUS, default=0)

    class Meta:
        ordering = ["-created_on"]

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        from django.urls import reverse
        return reverse("post_detail", kwargs={"slug": str(self.slug)})

Create a new file feeds.py inside the application directory.

from django.contrib.syndication.views import Feed
from django.template.defaultfilters import truncatewords
from .models import Post
from django.urls import reverse


class LatestPostsFeed(Feed):
    title = "My blog"
    link = ""
    description = "New posts of my blog."

    def items(self):
        return Post.objects.filter(status=1)

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

    def item_description(self, item):
        return truncatewords(item.content, 30)

    # Only needed if the model has no get_absolute_url method
    # def item_link(self, item):
    #     return reverse("post_detail", args=[item.slug])

The title, link, and description correspond to the standard RSS <title><link> and <description> elements, respectively.

The items() method retrieves the objects to be included in the feed. The item_title() and item_description() methods receive each object returned by items() and return the title and description for each item. We used truncatewords built-in template filter to build the description of the blog post with the first 30 words.

In order to retrieve links of items, you must either implement get_absolute_url() in the models all item_link() in the Post feed class.

Next map the feed in urls.py file.

from .feeds import LatestPostsFeed

urlpatterns = [
    path("feed/rss", LatestPostsFeed(), name="post_feed"),
               ]

Now Django will build RSS 2.0 feed at /feed/rss

Save the file run the server and navigate to http://127.0.0.1:8000/feed/rss you should see the XML file.

Use this XML Formatter tool to see the feed in a user-friendly form, here is an example feed.

<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
      <channel>
            <title>My blog</title>
            <link/>http://127.0.0.1:8000
            <description>
                  New posts of my blog.</description>
            <atom:link href="http://127.0.0.1:8000/feed/rss" rel="self">
            </atom:link>
            <language>en-us</language>
            <lastbuilddate>Fri, 03 Jan 2020 15:22:32 +0000</lastbuilddate>
            <item>
                  <title>Second Post</title>
                  <link/>http://127.0.0.1:8000/second-post/
                  <description>
                        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam feugiat velit diam. Etiam ut ex convallis, feugiat odio sit amet, mattis dolor. Suspendisse velit neque, sollicitudin placerat rhoncus ut, semper …</description>
                  <guid>http://127.0.0.1:8000/second-post/</guid>
            </item>
            <item>
                  <title>My First Ever Post</title>
                  <link/>http://127.0.0.1:8000/my-first-ever-post/
                  <description>
                        This is my first ever blog post</description>
                  <guid>http://127.0.0.1:8000/my-first-ever-post/</guid>
            </item>
      </channel>
</rss>

By default, Django produces RSS 2.0 Feeds to generate Atom feeds you can assign feed_type to Atom.

from django.utils.feedgenerator import Atom1Feed

class MyFeed(Feed):
    feed_type = Atom1Feed

To explore more visit – https://docs.djangoproject.com/en/3.0/ref/contrib/syndication/

Related Articles

6 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

Close