How to generate ATOM/RSS feed for Django website


In previous articles, we learned how to create a sitemap for the Django website. A valid sitemap increases your website's search engine ranking. Hence good for search engine optimization. 

Similarly, adding a robot.txt file is good for your website. It tells crawlers, which page to crawl and which page not to crawl for indexing.

In this article, we will see how to generate RSS feed on your Django website. 

The RSS feed help to keep up readers with their favorite blogs, news sites, and other websites. RSS allows the content and new updates to come to the reader. Generally, you use RSS to syndicate or subscribe to the feed of a website, blog or almost any media content that is updated online


Create a file in your app directory, parallel to urls.py file and name it feeds.py. Paste the below code in it. 

In the below sample example, we are fetching posts/articles from the database of pythoncircle.com. We have implemented four methods, item, item_title, item_description and item_link. The code has been updated with comments.


class LatestEntriesFeed(Feed):
title = "PythonCircle.com: New article for Python programmers every week"
link = "/feed/"
description = "Updates on changes and additions to python articles on pythoncircle.com."
# return 10 recently created/updated posts
def items(self):
return get_recent_updated_posts(number_of_posts=10)

def item_title(self, item):
return item.title
# return a short description of article
def item_description(self, item):
return item.description
# create and return the article URL
def item_link(self, item):
return reverse('appname:index', args=(item.post_id,))



Now in your project's urls.py file (not in any app's urls.py file) add below code.

from appname.feeds import LatestEntriesFeed()

# add feeds path
urlpatterns += [
path(r'feed/', LatestEntriesFeed()),
]


Restart/Reload your Django app and go to pythoncircle.com/feed/ or localhost:8000/feed/.

You can validate if RSS feed generated is valid or not.



How to create sitemap of Django website

A site map is a list of a website's content designed to help both users and search engines navigate the site.

A site map can be a hierarchical list of pages, an organization chart, or an XML document that provides instructions to search engine crawl bots.


Why sitemaps are required:

XML Sitemaps are important for SEO because they make it easier for Google to find your site's pages—this is important because Google ranks web PAGES, not just websites. There is no downside of having an XML Sitemap and having one can improve your SEO, so we highly recommend them.


Example:

The sitemap for this blog can be found at http://thepythondjango.com/sitemap_index.xml . 

creating sitemap of dynamic urls in your django application


Steps to add Sitemaps to your Django Application:

Create a file sitemap.py in your app.

Create two different classes in sitemap.py file, one for static pages and another for Dynamic URLs.

Let's assume your website sell some product where product details are stored in the database. Once a new product is added to the database, you want that product page to be searchable by search engines. We need to add all such product pages/URLs to sitemaps.


Static Sitemap:

Define a class StaticSitemap in your sitemap.py file. Define the mandatory function items in it which will return the list of objects.

These objects will be passed to the location method which will create URL from these objects. 

from django.contrib.sitemaps import Sitemap
from django.core.urlresolvers import reverse

class StaticSitemap(Sitemap):

    def items(self):
        return [
            'myapp:terms_and_conditions',
            'myapp:contact_us',
            'myapp:about_us'
        ]

    def location(self, item):
        return reverse(item)


Here in items function, we are returning appname:url_name which will be used by the location method to convert into an absolute URL.

Refer you app's urls.py file for URL names.


Dynamic Sitemap:

Similarly, we will create Dynamic sitemap by fetching values from DB. 

from mystore.models import ProductDetailsModel


class ProductSitemap(Sitemap):

    def items(self):
        return ProductDetailsModel.objects.all()

    def location(self, item):
        return reverse('myapp:product', args=[item.product_id])


Here we are getting all products from the database and generating URLs like http:example.com/product/12.



Adding sitemaps in URLconf:

Now add these sitemap class in URLconf. Edit the project's urls.py  file and add below code in it.

from mystore.sitemap import  StaticSitemap, ProductSitemap
from django.contrib.sitemaps.views import sitemap


sitemaps = {
 'pages': StaticSitemap,
 'products': ProductSitemap,
}

urlpatterns += [
    url(r'^sitemap.xml$', sitemap, {'sitemaps': sitemaps})
]

 

Now reload your server and go to localhost:8000/sitemap.xml and you will be able to see your sitemap there.  


Reference : 
https://docs.djangoproject.com/en/2.0/ref/contrib/sitemaps/   

Host your Django App for Free.


For loop in Django template


For loop is used to iterate over any iterable object, accessing one item at a time and making it available inside the for loop body.

For example, if you want to create a drop down of countries in Django template, you can use the below code.

{% for country in country_list %}
    <option name="{{country}}">{{country|title}}</option>
{% endfor %}


for is an inbuilt tag in Django template and it needs to be closed using endfor tag.



Iterating over a dictionary:

To iterate over a dictionary of people's name and their age, just like you would do in Python, use below code.

{% for name, age in data.items %}
    Name: {{name}}, Age: {{age}} <br>
{% endfor %}


Objects like data and country_list will be passed to the render function while rendering the template.

return render(request, 'appname/template_name.html', {"data":data, "country_list":country_list})



Checking if iterable used in for loop is empty:

Let's say you want to display new messages to logged in user. You fetched all the new messages from the database and stored them in a list and passed to render function along with the template. 

Now you can either check if the message list is empty or not and then display the message accordingly. Example:

{% if messages %}
    {% for message in messages %}
        {{ message }}<br>
    {% endfor %}
{% else %}
    <div>No new message for you</div>
{% endif %}

Or you can use {% empty %} tag along with {% for %} tag as below.

{% for message in messages %}
    {{ message }}
{% empty %}
    <div>No new message for you</div>
{% endfor %}



Break in Django for loop:

That might be a piece of bad news for you. There is no break statement in Django template For loop.

Depending on your requirement you can do one of the following.

Option 1 - Iterate over the whole list but do not perform any action if the condition is not matched.

For example, you are printing numbers from a list and you need to exit the list as soon as number 99 is encountered. Normally this would be done as below in Python.

for number in numbers:
    if 99 == number:
        break
    print(number)

But there is no break statement in Django template For loop. You can achieve the same functionality (almost) as below.

{% set isBreak = False %}
{% for number in numbers %}
    {% if 99 == number %}
        {% set isBreak = true %}
    {% endif %}

    {% if isBreak %}
        {# this is a comment. Do nothing. #}
    {% else %}
        <div>{{number}}</div>
    {% endif %}
{% endfor %}


Option 2 - You can create your own custom template tag



Iterating over a reversed list:

You can iterate over a list in reverse order using below code.

{% for member in member_list_score_wise reversed %}
    {{ member }} <br>
{% endfor %}



Accessing loop index inside the loop:

If you want to print the sequence number before the item being printed, you can use forloop.counter variable.

{% for member in member_list_score_wise reversed %}
    {{forloop.counter}}. {{ member }} <br>
{% endfor %}
1. John
2. Mac
3. Tony


Similarly, you can use the below variables:

forloop.counter0  - current index when started with 0
forloop.revcounter - index from last of the loop, started with 1
forloop.revcounter0 - index from last of the loop, started with 0
forloop.parentloop - parent loop index in nested For loops
forloop.first - return true if the current item is the first item of list
forloop.last - return true if the current item is the last item of the list



Range in Django template:

Sometimes you just need to run a loop N number of times. In such cases item at the current index doesn't matter. In python you would use range function. But again, there is no range tag or function in Django template. You can use either one of the below approaches.

Option 1 - Pass the list to render function along with template.

render(request, template.html, {"numbers": range(100)})

And in template

{% for number in numbers %}
    {{number}}
{% endfor %}


Option 2 - You can use the below code to emulate the range function.

{% for item in "x"|ljust:"100" %}
    {{item}} {# or do anything 100 times #}
{% endfor %}

ljust left-align the values in a field of the given width (100 in this case). So "x"|ljust:"10" will be "x         ". So basically you a string of length 10 with 9 spaces in it and 'x' as the first character. Now you are iterating over this string one character at a time.


Further Readings:

https://docs.djangoproject.com/en/2.2/ref/templates/builtins/
https://www.pythoncircle.com/post/42/creating-custom-template-tags-in-django/
https://djangosnippets.org/snippets/2093/
 



SUBSCRIBE
Please subscribe to get the latest articles in your mailbox.


Recent Posts:






© pythoncircle.com 2018-2019
Contact Us: code108labs [at] gmail.com
Address: 3747 Smithfield Avenue, Houston, Texas