Insights from Our Experts

Blog image

How to make optimized and faster Django websites

Author Image

Jibu James,Senior Software Engineer

Even after spending a great deal of time and effort, your Django application takes too much performance overhead and gets too slow after some reasonable amount of traffic? There are a couple of features and methods for optimizing the code and improving the overall user experience. 

The primary step is to learn about the elementary optimization techniques explained in Django's documentation.

 Read also: How to host your Django project to production server

1. SQL optimizations

It’s necessary to avoid the use of redundant code that makes excessive Django ORM queries. Avoid the use of repetitive evaluation of queries that cause repetitive database hits. Similarly, avoid the use of double evaluation of big queries.

class Product(models.Model):

    def count_similar_products(self):

return Product.objects.filter(type=self.type).count() 

Here, {{ product.count_similar_products }}will make the double evaluation. 

Also, the use of the Django Debug Toolbar helps a lot to monitor the SQL queries that are getting executed.

2. Caching

Caching is the process of keeping often requested objects ‘close’ so that they can be delivered fast. Computers and the internet would die without the use of caching. A cache is implemented in almost all components - processors, disks, operating systems, DNS, databases, browsers, etc. 

Before using Django’s cache framework, determine the pages that are most often served and concentrate primarily on those.

Different cache servers can be used in Django. Memcache is the most efficient one. To use Memcache with Django, define it in settings as: 


    'default': {

        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',

        'LOCATION': '',



Per view cache

A whole Django view can be cached with the cache_page. The cache_page decorator will cache the response returned from the view. 

from django.views.decorators.cache import cache_page

@cache_page(60 * 15)

def index(request):

    return render(request, 'index.html') 


Using the cached_property decorator saves the value returned. The next time when the function is called, it will return the saved value. 

from django.utils.functional import cached_property


class Product(models.Model):

def count_similar_products(self):

return Product.objects.filter(type=self.type).count()

select_related() and prefetch_related()

Hitting the database multiple times for different parts of a single ‘set’ of data is, in general, less efficient than retrieving it all in one query.

select_related() results in a single more complex query. But the later use of foreign-key relationships won’t require database queries.


# Hits the database.

e = Entry.objects.get(id=5)

# Hits the database again to get the related Blog object.

b = 

Using select_related():

# Hits the database.

e = Entry.objects.select_related('blog').get(id=5)

# Doesn't hit the database, because has been prepopulated in the previous query.

b =


While select_related() offers you an advantage on foreign-key relationships, prefetch_related can be used for ManyToManyField and their relationships.

Template Fragments

You can cache template fragments using the cache template tag. To give your template access to this tag, add {% cache %}template tag caches the contents of the block for a given amount of time. It takes at least two arguments: the cache timeout (in seconds), and the name to give the cache fragment. 

{% load cache %}

{% cache 600 test_fragment %}

{% trans "SayOne Technologies" %}

{% endcache %}


Session Caching

Session caching eliminates the need to load session data from sources like a database; instead, stores frequently used session data in memory.


SESSION_ENGINE = 'django.contrib.sessions.backends.cache' 


Object Caching

At times, caching an entire rendered page doesn’t gain you very much, it incurs more overhead. Your site may include a view whose results depend on several complex queries. You wouldn’t want to cache the entire result, but just the values which rarely change. In this case, it would not be ideal to use the full-page caching that the per-site or per-view cache offer. To tackle this case, Django uses a low-level cache API to store objects in the cache.

from django.core.cache import cache

cache.set(‘Python’, ‘Django’, timeout=600)





Caching outside Django

Caching can also be done using other strategies like web servers, reverse proxies, and CDNs (Content Delivery Networks) like Cloudflare. 

3. Avoid user waiting time

Other useful techniques that can be adopted for optimization include:

  - Scheduling the execution of events like confirmation emails.

  - Process any requests that are guaranteed to time-out, using asynchronous methods.

  - Use of Celery / Gevent for scheduling.

  - Use of template engines like Jinja2 for faster rendering. Django 1.8 provides built-in support for Jinja2.

Also, don’t forget to log all the database queries. Closely monitoring of these logs will help you to identify the queries taking too much time, and work around until these queries become faster. Connecting more servers to the architecture can also come in handy, for reduced load times.

Read also: When should you choose Django Framework

Optimization techniques are essential to give your users a flawless experience. The real test of a website or application happens in a real scenario with multiple users accessing it simultaneously, and nothing is more critical than functionalities and features that execute without any delay. The above explained are some of the basic techniques, and it will be of great utility to make yourself well-versed with the various optimization techniques.

Get in touch for further information and FREE! Consultation. SayOne creates high performance software solutions tailored to meet your needs.


I Need

Help for