Advertisement
  1. Code
  2. Python
  3. Django

How to Cache Using Redis in Django Applications

Scroll to top

One of the ways to relieve strain on a server is by caching data. This is done by caching data after it has been processed and then serving it from the cache the next time it is requested. This tutorial will give a detailed discussion of Redis, explaining how to install Redis and cache data in Python applications.

Introduction to Redis and Caching

Caching refers to storing the server response in the client itself, so that a client need not make a server request for the same resource again and again. A server response should have information about how caching is to be done, so that a client caches the response for a time period or never caches the server response.

A cache, on the other hand, is a hardware or software component that is used to store data so future requests for the same data can be served faster.

In this age where users expect results within a second, it is wise to serve requests by reading data from the cache, which is ultimately faster than reading from a slower data store; thus, the system performance depends on how many requests can be served from the cache.

Redis is an open-source, in-memory data structure store, used as a database, cache, and message broker. It works by storing data in a cache and providing it the next time it is requested, instead of querying the database every time.

Install Redis

Redis is already included in the official package repository of Ubuntu. To install the latest version of Redis server, run the following commands one after the other.

1
sudo apt-get update
2
sudo apt install redis

After installing Redis, you can check its version with the following command:

1
redis-cli --version

If you're on Windows, you can run Redis using Windows Subsystem for Linux, also known as WSL2. WSL2 basically lets you run a Linux environment (command-line tools, utilities, applications, etc.) directly on your Windows machine.

To install and run Redis on Windows, you'll first need to run the following command on your local Powershell terminal to enable Windows Subsystem for Linux (make sure you run this as an administrator):

1
 Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux

Next, open Microsoft Store on your Windows machine, search for Ubuntu, and install it. This gives you access to the Ubuntu terminal, which is where you'll run the command to install Redis.

Ubuntu terminalUbuntu terminalUbuntu terminal
Ubuntu terminal

Once Ubuntu is installed, launch the terminal and enter your UNIX username and password. Then run these commands in succession to install Redis:

1
sudo apt-add-repository ppa:redislabs/redis
2
sudo apt-get update
3
sudo apt-get upgrade
4
sudo apt-get install redis-server

Run the following command to start your server:

1
 sudo service redis-server restart

Django API Example

Let's create our Django project. Our project will be able to cache all the products in a store, making it easy and fast to retrieve data in subsequent queries.

To make use of Redis in our app, we need to do the following:

  1. Check if results for the current query exist in the cache.
  2. If results exist in the cache, retrieve them.
  3. If results don't exist, fetch them, store them in the cache, and then forward them to the requesting entity.

Requirements

  • Django
  • django-redis
  • Redis
  • loadtest

Create Your Project

Before we get started, create a directory and install a virtual environment. A virtual environment will let you install library versions required by your application.

1
mkdir myprojects
2
3
cd myprojects

Next, activate the virtual environment and install the project requirements.

1
 source venv/bin/activate
2
 
3
 pip install django==1.9
4
 
5
 pip install django-redis
6
 
7
 pip install djangorestframework

Create a Django Project

1
django-admin startproject django_cache

Create a new app called store, which will handle product management in our store.

1
cd django_cache
2
3
python manage.py startapp store

Add the store application and rest_framework to the list of installed apps in the settings.py file.

1
# settings.py

2
INSTALLED_APPS = [
3
    'django.contrib.admin',
4
    'django.contrib.auth',
5
    'django.contrib.contenttypes',
6
    'django.contrib.sessions',
7
    'django.contrib.messages',
8
    'django.contrib.staticfiles',
9
    'store', # add here

10
    'rest_framework', # add here too

11
]

Creating the Models

In store/models.py, we start by creating the Product model for storing the product details as follows:

1
from __future__ import unicode_literals
2
from django.db import models
3
import datetime
4
5
# Create your models here.

6
7
8
class Product(models.Model):
9
10
    name = models.CharField(max_length=255)
11
    description = models.TextField(null=True, blank=True)
12
    price = models.IntegerField(null=True, blank=True)
13
    date_created = models.DateTimeField(auto_now_add=True, blank=True)
14
    date_modified = models.DateTimeField(auto_now=True, blank=True)
15
16
    def __unicode__(self):
17
        return self.name
18
19
    def to_json(self):
20
        return {
21
            'id': self.id,
22
            'name': self.name,
23
            'desc': self.description,
24
            'price': self.price,
25
            'date_created': self.date_created,
26
            'date_modified': self.date_modified
27
        }

Migrations

Create an initial migration for our products model, and sync the database for the first time.

1
python manage.py makemigration store
2
3
python manage.py migrate

Create superuser

Create a superuser, log in to the admin panel, and populate your database with some sample data which we will use to do our tests.

1
python manage.py createsuperuser

Configuring Redis in Python Applications

In order to use Redis with a Django application, we need to set up Redis to store the application’s cache data. And the following to your settings.py file:

1
CACHES = {
2
    'default': {
3
        'BACKEND': 'django_redis.cache.RedisCache',
4
        'LOCATION': 'redis://127.0.0.1:6379/',
5
        'OPTIONS': {
6
            'CLIENT_CLASS': 'django_redis.client.DefaultClient',
7
        }
8
    }
9
}

Next, we are going to create an endpoint that retrieves all the products from our database. We will first test the performance of the application in terms of how long it takes to retrieve data from the database without caching it. We will then implement another endpoint that retrieves data from a cache and compare the performance.

In store/views.py, add the following code which retrieves all the products present in the database.

1
from django.shortcuts import render
2
from rest_framework.decorators import api_view
3
from rest_framework.response import Response
4
from rest_framework import status
5
6
# Create your views here.

7
8
9
10
@api_view(['GET'])
11
def view_books(request):
12
13
    products = Product.objects.all()
14
    results = [product.to_json() for product in products]
15
    return Response(results, status=status.HTTP_201_CREATED)

Configuring URLs

Create a file store/urls.py and add the following code.

1
# store/urls.py

2
from django.conf.urls import url
3
from .views import view_books
4
5
6
urlpatterns = [
7
    url(r'^$', view_books),
8
]

We also need to import URLs from the users application to the main django_cache/urls.py file.

1
# django_cache/urls.py

2
3
from django.conf.urls import url, include
4
from django.contrib import admin
5
6
urlpatterns = [
7
    url(r'^admin/', admin.site.urls),
8
    url(r'^store/', include('store.urls'))
9
]

Let's do a test and see if we are on track. We will be using loadtest. If you are not familiar with loadtest, it's a tool for testing performance.

Installing loadtest as root is simple:

1
sudo npm install -g loadtest
1
$ loadtest -n 100 -k  https://localhost:8000/store/
2
3
# result

4
INFO Requests per second: 55
5

As seen from the above, 55 requests are processed per second.

Let's create another endpoint for retrieving data after caching with Redis. Edit users/views.py to match the following:

1
from rest_framework.decorators import api_view
2
from rest_framework import status
3
from rest_framework.response import Response
4
from django.core.cache import cache
5
from django.conf import settings
6
from django.core.cache.backends.base import DEFAULT_TIMEOUT
7
8
CACHE_TTL = getattr(settings, 'CACHE_TTL', DEFAULT_TIMEOUT)
9
from .models import Product
10
11
12
# Create your views here.

13
14
15
@api_view(['GET'])
16
def view_books(request):
17
    # rest of the code

18
19
20
@api_view(['GET'])
21
def view_cached_books(request):
22
    if 'product' in cache:
23
        # get results from cache

24
        products = cache.get('product')
25
        return Response(products, status=status.HTTP_201_CREATED)
26
27
    else:
28
        products = Product.objects.all()
29
        results = [product.to_json() for product in products]
30
        # store data in cache

31
        cache.set(product, results, timeout=CACHE_TTL)
32
        return Response(results, status=status.HTTP_201_CREATED)
33

The code above will check if the key product is present in the cache, and if found, the data represented will be returned to the browser. In the event that no data is present in the cache, we first retrieve the data from the database, store it in the cache, and then return the data queried to the browser.

Update store/urls.py as follows.

1
from django.conf.urls import url
2
from .views import view_books, view_cached_books
3
4
5
urlpatterns = [
6
    url(r'^$', view_books),
7
    url(r'^cache/', view_cached_books),
8
9
]

Let's carry out the tests.

1
$ loadtest -n 100 -k  http://localhost:8000/store/cache/
2
3
# results

4
INFO Requests per second: 233
5
6

The first time you hit the endpoint localhost:8000/store/cache, the application will query from the database and return data, but subsequent calls to the URL will bypass the database and query from the cache since the data is already available in the cache.

Conclusion

In this tutorial, we used Redis to give an application the illusion of speed. We leverage the use of RAM in Redis to store the results of queries and then return those results from the cache in subsequent queries rather than doing the round trip to the database.

There are other caching tools available, such as Memcached, which is similar to Redis. However, Redis is more popular than Memcached because it takes only a few minutes to set up and get working in applications. Redis has more sophisticated mechanisms as it has been described as a "data structure store", thus making it more powerful and flexible. Redis also has a larger advantage because you can store data in any form.

Hopefully, this tutorial has shown you how easy it is to add a caching layer to your application, hence improving performance. Caching must be something to consider when you need to reduce loading times and server costs.

Post thumbnail image generated by OpenAI DALL-E.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.