django-redis
Full featured redis cache backend for Django.
Rank: #1285Downloads: 8,630,040 (30 days)Stars: 3,056Forks: 444
Description
==============================
Redis cache backend for Django
==============================
.. image:: https://jazzband.co/static/img/badge.svg
:target: https://jazzband.co/
:alt: Jazzband
.. image:: https://github.com/jazzband/django-redis/actions/workflows/ci.yml/badge.svg
:target: https://github.com/jazzband/django-redis/actions/workflows/ci.yml
:alt: GitHub Actions
.. image:: https://codecov.io/gh/jazzband/django-redis/branch/master/graph/badge.svg
:target: https://codecov.io/gh/jazzband/django-redis
:alt: Coverage
.. image:: https://img.shields.io/pypi/v/django-redis.svg?style=flat
:target: https://pypi.org/project/django-redis/
This is a `Jazzband <https://jazzband.co>`_ project. By contributing you agree
to abide by the `Contributor Code of Conduct
<https://jazzband.co/about/conduct>`_ and follow the `guidelines
<https://jazzband.co/about/guidelines>`_.
Introduction
------------
django-redis is a BSD licensed, full featured Redis cache and session backend
for Django.
Why use django-redis?
~~~~~~~~~~~~~~~~~~~~~
- Uses native redis-py url notation connection strings
- Pluggable clients
- Pluggable parsers
- Pluggable serializers
- Primary/secondary support in the default client
- Comprehensive test suite
- Used in production in several projects as cache and session storage
- Supports infinite timeouts
- Facilities for raw access to Redis client/connection pool
- Highly configurable (can emulate memcached exception behavior, for example)
- Unix sockets supported by default
Requirements
~~~~~~~~~~~~
- `Python`_ 3.9+
- `Django`_ 4.2+
- `redis-py`_ 4.0.2+
- `Redis server`_ 2.8+
.. _Python: https://www.python.org/downloads/
.. _Django: https://www.djangoproject.com/download/
.. _redis-py: https://pypi.org/project/redis/
.. _Redis server: https://redis.io/download
User guide
----------
Installation
~~~~~~~~~~~~
Install with pip:
.. code-block:: console
$ python -m pip install django-redis
Configure as cache backend
~~~~~~~~~~~~~~~~~~~~~~~~~~
To start using django-redis, you should change your Django cache settings to
something like:
.. code-block:: python
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/1",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
}
}
django-redis uses the redis-py native URL notation for connection strings, it
allows better interoperability and has a connection string in more "standard"
way. Some examples:
- ``redis://[[username]:[password]]@localhost:6379/0``
- ``rediss://[[username]:[password]]@localhost:6379/0``
- ``unix://[[username]:[password]]@/path/to/socket.sock?db=0``
Three URL schemes are supported:
- ``redis://``: creates a normal TCP socket connection
- ``rediss://``: creates a SSL wrapped TCP socket connection
- ``unix://`` creates a Unix Domain Socket connection
There are several ways to specify a database number:
- A ``db`` querystring option, e.g. ``redis://localhost?db=0``
- If using the ``redis://`` scheme, the path argument of the URL, e.g.
``redis://localhost/0``
When using `Redis' ACLs <https://redis.io/topics/acl>`_, you will need to add the
username to the URL (and provide the password with the Cache ``OPTIONS``).
The login for the user ``django`` would look like this:
.. code-block:: python
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://django@localhost:6379/0",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"PASSWORD": "mysecret"
}
}
}
An alternative would be write both username and password into the URL:
.. code-block:: python
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://django:mysecret@localhost:6379/0",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
}
}
In some circumstances the password you should use to connect Redis
is not URL-safe, in this case you can escape it or just use the
convenience option in ``OPTIONS`` dict:
.. code-block:: python
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/1",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"PASSWORD": "mysecret"
}
}
}
Take care, that this option does not overwrites the password in the uri, so if
you have set the password in the uri, this settings will be ignored.
Configure as session backend
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Django can by default use any cache backend as session backend and you benefit
from that by using django-redis as backend for session storage without
installing any additional backends:
.. code-block:: python
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "default"
Testing with django-redis
~~~~~~~~~~~~~~~~~~~~~~~~~
django-redis supports customizing the underlying Redis client (see "Pluggable
clients"). This can be used for testing purposes.
In case you want to flush all data from the cache after a test, add the
following lines to your test class:
.. code-block:: python
from django_redis import get_redis_connection
def tearDown(self):
get_redis_connection("default").flushall()
Advanced usage
--------------
Pickle version
~~~~~~~~~~~~~~
For almost all values, django-redis uses pickle to serialize objects.
The ``pickle.DEFAULT_PROTOCOL`` version of pickle is used by default to ensure safe upgrades and compatibility across Python versions.
If you want set a concrete version, you can do it, using ``PICKLE_VERSION`` option:
.. code-block:: python
CACHES = {
"default": {
# ...
"OPTIONS": {
"PICKLE_VERSION": -1 # Will use highest protocol version available
}
}
}
Socket timeout
~~~~~~~~~~~~~~
Socket timeout can be set using ``SOCKET_TIMEOUT`` and
``SOCKET_CONNECT_TIMEOUT`` options:
.. code-block:: python
CACHES = {
"default": {
# ...
"OPTIONS": {
"SOCKET_CONNECT_TIMEOUT": 5, # seconds
"SOCKET_TIMEOUT": 5, # seconds
}
}
}
``SOCKET_CONNECT_TIMEOUT`` is the timeout for the connection to be established
and ``SOCKET_TIMEOUT`` is the timeout for read and write operations after the
connection is established.
Compression support
~~~~~~~~~~~~~~~~~~~
django-redis comes with compression support out of the box, but is deactivated
by default. You can activate it setting up a concrete backend:
.. code-block:: python
CACHES = {
"default": {
# ...
"OPTIONS": {
"COMPRESSOR": "django_redis.compressors.zlib.ZlibCompressor",
}
}
}
Let see an example, of how make it work with *lzma* compression format:
.. code-block:: python
import lzma
CACHES = {
"default": {
# ...
"OPTIONS": {
"COMPRESSOR": "django_redis.compressors.lzma.LzmaCompressor",
}
}
}
*Lz4* compression support (requires the lz4 library):
.. code-block:: python
import lz4
CACHES = {
"default": {
# ...
"OPTIONS": {
"COMPRESSOR": "django_redis.compressors.lz4.Lz4Compressor",
}
}
}
*Zstandard (zstd)* compression support (requires the pyzstd library):
.. code-block:: python
import pyzstd
CACHES = {
"default": {
# ...
"OPTIONS": {
"COMPRESSOR": "django_redis.compressors.zstd.ZStdCompressor",
}
}
}
*Gzip* compression support:
.. code-block:: python
import gzip
CACHES = {
"default": {
# ...
"OPTIONS": {
"COMPRESSOR": "django_redis.compressors.gzip.GzipCompressor",
}
}
}
Memcached exceptions behavior
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In some situations, when Redis is only used for cache, you do not want
exceptions when Redis is down. This is default behavior in the memcached
backend and it can be emulated in django-redis.
For setup memcached like behaviour (ignore connection exceptions), you should
set ``IGNORE_EXCEPTIONS`` settings on your cache configuration:
.. code-block:: python
CACHES = {
"default": {
# ...
"OPTIONS": {
"IGNORE_EXCEPTIONS": True,
}
}
}
Also, you can apply the same settings to all configured caches, you can set the global flag in
your settings:
.. code-block:: python
DJANGO_REDIS_IGNORE_EXCEPTIONS = True
Log Ignored Exceptions
~~~~~~~~~~~~~~~~~~~~~~
When ignoring exceptions with ``IGNORE_EXCEPTIONS`` or
``DJANGO_REDIS_IGNORE_EXCEPTIONS``, you may optionally log exceptions using the
global variable ``DJANGO_REDIS_LOG_IGNORED_EXCEPTIONS`` in your settings file::
DJANGO_REDIS_LOG_IGNORED_EXCEPTIONS = True
If you wish to specify the logger in which the exceptions are output, simply
set the global variable ``DJANGO_REDIS_LOGGER`` to the string name and/or path
of the desired logger. This will default to ``__name__`` if no logger is
specified and ``DJANGO_REDIS_LOG_IGNORED_EXCEPTIONS`` is ``True``::
DJANGO_REDIS_LOGGER = 'some.specified.logger'
Infinite timeout
~~~~~~~~~~~~~~~~
django-redis comes with infinite timeouts support out of the box. And it
behaves in same way as django backend contract specifies:
- ``timeout=0`` expires the value immediately.
- ``timeout=None`` infinite timeout
.. code-block:: python
cache.set("key", "value", timeout=None)
Get ttl (time-to-live) from key