Add RSS Feed to your Django site
Tags: django, beginners, codenewbie, python
Published: 2021-02-24 01:32:01

**you can jump to step 4 if you want to test it with your existing project**

<h1>Index</h1>
1- [Intorduction](#introduction)
2- [Environment Setup](#environment)
3- [Project Setup](#project)
4- [Add RSS Feed](#rss)


##Introduction <a name="introduction"></a>
**RSS** stands for <u>R</u>eally <u>S</u>imple <u>S</u>yndication it allows users and applications to access updates to your website. or simply it informs users or visitors about updates in your website.


##Environment Setup<a name="environment"></a>
* create your virtual environment or use an existing one: `python -m venv env`
* activate your virtual environment `source env/bin/activate`
* install Django `pip install django`


##Project Setup <a name="project"></a>
* create new folder `mkdir django-add-rssfeed && cd django-add-rssfeed`
* create new project `django-admin startproject config .`
* create new app `python manage.py startapp blog` and add it to `INSTALLED_APPS`
* edit `blog/models.py` and paste these code in it:
```
from django.db import models
from django.urls import reverse

class Post(models.Model):
    STATUS_CHOICES = [('published', 'Published'), ('draft', 'Draft')]
    title = models.CharField(max_length=250)
    content = models.TextField()
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)
    status = models.CharField(max_length=12, choices=STATUS_CHOICES, default='draft')

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse('post-detail', kwargs={'slug': self.slug})

@receiver(post_save, sender=Post)
def save_slug(sender, instance=None, created=False, **kwargs):
    if created:
        instance.slug = slugify(instance.title)
        instance.save()
```
* run `python manage.py makemigrations` then `python manage.py migrate` and don't forget to create a superuser `python manage.py createsuperuser`
* add Post to `admin.py` and add some data for testing later.


## Add RSS Feed <a name="rss"></a>
* Create a new file `blog/feeds.py` and put this code in it.
```
from django.contrib.syndication.views import Feed
from django.utils.feedgenerator import Atom1Feed #optional

from .models import Post

class PostFeed(Feed):
    feed_type = Atom1Feed #optional
    title = "My Blog"
    link = ""
    description = "New Posts of My Blog"

    def items(self):
        return Post.objects.filter(status='published')
    
    def item_title(self, item):
        return item.title
    
    def item_description(self, item):
        return truncatewords(item.content, 30) # item.content
```
`items()` returns a list of objects that should be included in the feed as `<item>` elements. and so `item_title` and `item_description` are used to return a single object which will be included in `<title>` and `<description>` elements.
if you don't have `get_absolute_url` in your model you must override `item_link(self, item)` which returns reversed URL.
`feed_type` is an optional attribute, it is used to change Feed Type, By default, feeds produced by Django use RSS 2.0.
* and now map it to a `blog/urls.py`:
```
from .feeds import PostFeed

urlpatterns = [
    .......
    path("feed/rss", PostFeed(), name="post-feed"),
    ......
]
```

here is how it looks like:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1y7gmgj6nf7anwd9hxop.jpg)


source code is upload to github: https://github.com/abdulshak1999/Python/tree/main/django/website_rssfeed

for more information check this: https://docs.djangoproject.com/en/3.1/ref/contrib/syndication/