File: README.rst
============================== 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.10+
- `Django`_ 5.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 backendTo 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",
}
}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/0rediss://[[username]:[password]]@localhost:6379/0unix://[[username]:[password]]@/path/to/socket.sock?db=0
Three URL schemes are supported:
redis://: creates a normal TCP socket connectionrediss://: creates a SSL wrapped TCP socket connectionunix://creates a Unix Domain Socket connection
There are several ways to specify a database number:
- A
dbquerystring 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 and the password in the connection string or in OPTIONS with
the keys USERNAME and PASSWORD. NOTE: Values in the connection string
have precedence!
The login for the user django would look like this:
.. code-block:: python
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://django:mysecret@localhost:6379/0",
}
}Instead you may specify both of these values in OPTIONS:
.. code-block:: python
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://localhost:6379/0",
"OPTIONS": {
"USERNAME": "django",
"PASSWORD": "mysecret",
}
}
}And, finally you may mix the two as follows (be sure not to include a password,
even if blank in the connection string):
.. code-block:: python
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://django@localhost:6379/0",
"OPTIONS": {"PASSWORD": "mysecret"}
}
}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 behaviorIn 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 = TrueLog 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 keyWith Redis, you can access to ttl of any stored key, for it, django-redis
exposes ttl function.
It returns:
- 0 if key does not exists (or already expired).
- None for keys that exists but does not have any expiration.
- ttl value for any volatile key (any key that has expiration).
.. code-block:: pycon
>>> from django.core.cache import cache
>>> cache.set("foo", "value", timeout=25)
>>> cache.ttl("foo")
25
>>> cache.ttl("not-existent")
0With Redis, you can access to ttl of any stored key in milliseconds, for it, django-redis
exposes pttl function.
.. code-block:: pycon
>>> from django.core.cache import cache
>>> cache.set("foo", "value", timeout=25)
>>> cache.pttl("foo")
25000
>>> cache.pttl("not-existent")
0Expire & Persist
Additionally to the simple ttl query, you can send persist a concrete key or
specify a new expiration timeout using the ``persist`` and ``expire`` methods:
.. code-block:: pycon
>>> cache.set("foo", "bar", timeout=22)
>>> cache.ttl("foo")
22
>>> cache.persist("foo")
True
>>> cache.ttl("foo")
None
.. code-block:: pycon
>>> cache.set("foo", "bar", timeout=22)
>>> cache.expire("foo", timeout=5)
True
>>> cache.ttl("foo")
5
The ``expire_at`` method can be used to make the key expire at a specific moment in time.
.. code-block:: pycon
>>> cache.set("foo", "bar", timeout=22)
>>> cache.expire_at("foo", datetime.now() + timedelta(hours=1))
True
>>> cache.ttl("foo")
3600
The ``pexpire_at`` method can be used to make the key expire at a specific moment in time with milliseconds precision:
.. code-block:: pycon
>>> cache.set("foo", "bar", timeout=22)
>>> cache.pexpire_at("foo", datetime.now() + timedelta(milliseconds=900, hours=1))
True
>>> cache.ttl("foo")
3601
>>> cache.pttl("foo")
3600900
The ``pexpire`` method can be used to provide millisecond precision:
.. code-block:: pycon
>>> cache.set("foo", "bar", timeout=22)
>>> cache.pexpire("foo", timeout=5500)
True
>>> cache.pttl("foo")
5500
Locks
~~~~~
It also supports the Redis ability to create Redis distributed named locks. The
Lock interface is identical to the ``threading.Lock`` so you can use it as
replacement.
.. code-block:: python
with cache.lock("somekey"):
do_some_thing()
Scan & Delete keys in bulkdjango-redis comes with some additional methods that help with searching or
deleting keys using glob patterns.
.. code-block:: pycon
>>> from django.core.cache import cache
>>> cache.keys("foo_*")
["foo_1", "foo_2"]A simple search like this will return all matched values. In databases with a
large number of keys this isn't suitable method. Instead, you can use theiter_keys function that works like the keys function but uses Redis
server side cursors. Calling iter_keys will return a generator that you can
then iterate over efficiently.
.. code-block:: pycon
>>> from django.core.cache import cache
>>> cache.iter_keys("foo_*")
<generator object algo at 0x7ffa9c2713a8>
>>> next(cache.iter_keys("foo_*"))
"foo_1"For deleting keys, you should use delete_pattern which has the same glob
pattern syntax as the keys function and returns the number of deleted keys.
.. code-block:: pycon
>>> from django.core.cache import cache
>>> cache.delete_pattern("foo_*")To achieve the best performance while deleting many keys, you should set DJANGO_REDIS_SCAN_ITERSIZE to a relatively
high number (e.g., 100_000) by default in Django settings or pass it directly to the delete_pattern.
.. code-block:: pycon
>>> from django.core.cache import cache
>>> cache.delete_pattern("foo_*", itersize=100_000)Redis native commands
django-redis has limited support for some Redis atomic operations, such as the
commands ``SETNX`` and ``INCR``.
You can use the ``SETNX`` command through the backend ``set()`` method with the
``nx`` parameter:
.. code-block:: pycon
>>> from django.core.cache import cache
>>> cache.set("key", "value1", nx=True)
True
>>> cache.set("key", "value2", nx=True)
False
>>> cache.get("key")
"value1"
Also, the ``incr`` and ``decr`` methods use Redis atomic operations when the
value that a key contains is suitable for it.
Raw client access
~~~~~~~~~~~~~~~~~
In some situations your application requires access to a raw Redis client to
use some advanced features that aren't exposed by the Django cache interface.
To avoid storing another setting for creating a raw connection, django-redis
exposes functions with which you can obtain a raw client reusing the cache
connection string: ``get_redis_connection(alias)``.
.. code-block:: pycon
>>> from django_redis import get_redis_connection
>>> con = get_redis_connection("default")
>>> con
<redis.client.Redis object at 0x2dc4510>
WARNING: Not all pluggable clients support this feature.
Connection pools
~~~~~~~~~~~~~~~~
Behind the scenes, django-redis uses the underlying redis-py connection pool
implementation, and exposes a simple way to configure it. Alternatively, you
can directly customize a connection/connection pool creation for a backend.
The default redis-py behavior is to not close connections, recycling them when
possible.
Configure default connection pool
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The default connection pool is simple. For example, you can customize the
maximum number of connections in the pool by setting ``CONNECTION_POOL_KWARGS``
in the ``CACHES`` setting:
.. code-block:: python
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
# ...
"OPTIONS": {
"CONNECTION_POOL_KWARGS": {"max_connections": 100}
}
}
}
You can verify how many connections the pool has opened with the following
snippet:
.. code-block:: python
from django_redis import get_redis_connection
r = get_redis_connection("default") # Use the name you have defined for Redis in settings.CACHES
connection_pool = r.connection_pool
print("Created connections so far: %d" % connection_pool._created_connections)
Since the default connection pool passes all keyword arguments it doesn't use
to its connections, you can also customize the connections that the pool makes
by adding those options to ``CONNECTION_POOL_KWARGS``:
.. code-block:: python
CACHES = {
"default": {
# ...
"OPTIONS": {
"CONNECTION_POOL_KWARGS": {"max_connections": 100, "retry_on_timeout": True}
}
}
}
Use your own connection pool subclass
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Sometimes you want to use your own subclass of the connection pool. This is
possible with django-redis using the ``CONNECTION_POOL_CLASS`` parameter in the
backend options.
.. code-block:: python
from redis.connection import ConnectionPool
class MyOwnPool(ConnectionPool):
# Just doing nothing, only for example purpose
pass
.. code-block:: python
# Omitting all backend declaration boilerplate code.
"OPTIONS": {
"CONNECTION_POOL_CLASS": "myproj.mypool.MyOwnPool",
}
Customize connection factory
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If none of the previous methods satisfies you, you can get in the middle of the
django-redis connection factory process and customize or completely rewrite it.
By default, django-redis creates connections through the
``django_redis.pool.ConnectionFactory`` class that is specified in the global
Django setting ``DJANGO_REDIS_CONNECTION_FACTORY``.
.. code-block:: python
class ConnectionFactory(object):
def get_connection_pool(self, params: dict):
# Given connection parameters in the `params` argument, return new
# connection pool. It should be overwritten if you want do
# something before/after creating the connection pool, or return
# your own connection pool.
pass
def get_connection(self, params: dict):
# Given connection parameters in the `params` argument, return a
# new connection. It should be overwritten if you want to do
# something before/after creating a new connection. The default
# implementation uses `get_connection_pool` to obtain a pool and
# create a new connection in the newly obtained pool.
pass
def get_or_create_connection_pool(self, params: dict):
# This is a high layer on top of `get_connection_pool` for
# implementing a cache of created connection pools. It should be
# overwritten if you want change the default behavior.
pass
def make_connection_params(self, url: str) -> dict:
# The responsibility of this method is to convert basic connection
# parameters and other settings to fully connection pool ready
# connection parameters.
pass
def connect(self, url: str):
# This is really a public API and entry point for this factory
# class. This encapsulates the main logic of creating the
# previously mentioned `params` using `make_connection_params` and
# creating a new connection using the `get_connection` method.
pass
Use the sentinel connection factory
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In order to facilitate using `Redis Sentinels`_, django-redis comes with a
built in sentinel connection factory, which creates sentinel connection pools.
In order to enable this functionality you should add the following:
.. code-block:: python
# Enable the alternate connection factory.
DJANGO_REDIS_CONNECTION_FACTORY = 'django_redis.pool.SentinelConnectionFactory'
# These sentinels are shared between all the examples, and are passed
# directly to redis Sentinel. These can also be defined inline.
SENTINELS = [
('sentinel-1', 26379),
('sentinel-2', 26379),
('sentinel-3', 26379),
]
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
# The hostname in LOCATION is the primary (service / master) name
"LOCATION": "redis://service_name/db",
"OPTIONS": {
# While the default client will work, this will check you
# have configured things correctly, and also create a
# primary and replica pool for the service specified by
# LOCATION rather than requiring two URLs.
"CLIENT_CLASS": "django_redis.client.SentinelClient",
# Sentinels which are passed directly to redis Sentinel.
"SENTINELS": SENTINELS,
# kwargs for redis Sentinel (optional). Example with auth on sentinels
"SENTINEL_KWARGS": {
"username": "sentinel-user",
"password": "sentinel-pass",
},
# You can still override the connection pool (optional).
"CONNECTION_POOL_CLASS": "redis.sentinel.SentinelConnectionPool",
},
},
# A minimal example using the SentinelClient.
"minimal": {
"BACKEND": "django_redis.cache.RedisCache",
# The SentinelClient will use this location for both the primaries
# and replicas.
"LOCATION": "redis://minimal_service_name/db",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.SentinelClient",
"SENTINELS": SENTINELS,
},
},
# A minimal example using the DefaultClient.
"other": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": [
# The DefaultClient is [primary, replicas...], but with the
# SentinelConnectionPool it only requires one "is_master=0".
"redis://other_service_name/db?is_master=1",
"redis://other_service_name/db?is_master=0",
],
"OPTIONS": {"SENTINELS": SENTINELS},
},
# A minimal example only using only replicas in read only mode (and
# the DefaultClient).
"readonly": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://readonly_service_name/db?is_master=0",
"OPTIONS": {"SENTINELS": SENTINELS},
},
}
It is also possible to set some caches as sentinels and some as not:
.. code-block:: python
SENTINELS = [
('sentinel-1', 26379),
('sentinel-2', 26379),
('sentinel-3', 26379),
]
CACHES = {
"sentinel": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://service_name/db",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.SentinelClient",
"SENTINELS": SENTINELS,
"CONNECTION_POOL_CLASS": "redis.sentinel.SentinelConnectionPool",
"CONNECTION_FACTORY": "django_redis.pool.SentinelConnectionFactory",
},
},
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/1",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
},
},
}
.. _Redis Sentinels: https://redis.io/topics/sentinel
Pluggable parsers
~~~~~~~~~~~~~~~~~
`redis-py`_, the Python Redis client used by django-redis, will automatically
use a C-based parser if the `hiredis`_ package is installed in your environment.
This can provide a significant performance boost for parsing Redis replies.
To take advantage of this, simply install the `hiredis` package with pip:
.. code-block:: console
$ python -m pip install hiredis
No additional configuration in your Django settings is required. django-redis
will use the faster parser automatically.
.. _hiredis: https://pypi.org/project/hiredis/
Pluggable clients
~~~~~~~~~~~~~~~~~
django-redis is designed for to be very flexible and very configurable. For it,
it exposes a pluggable backends that make easy extend the default behavior, and
it comes with few ones out the box.
Default client
^^^^^^^^^^^^^^
Almost all about the default client is explained, with one exception: the
default client comes with replication support.
To connect to a Redis replication setup, you should change the ``LOCATION`` to
something like:
.. code-block:: python
"LOCATION": [
"redis://127.0.0.1:6379/1",
"redis://127.0.0.1:6378/1",
]
The first connection string represents the primary server and the rest to
replica servers.
WARNING: Replication setup is not heavily tested in production environments.
Shard client
^^^^^^^^^^^^
This pluggable client implements client-side sharding. It inherits almost all
functionality from the default client. To use it, change your cache settings to
something like this:
.. code-block:: python
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": [
"redis://127.0.0.1:6379/1",
"redis://127.0.0.1:6379/2",
],
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.ShardClient",
}
}
}
WARNING: Shard client is still experimental, so be careful when using it in
production environments.
Herd client
^^^^^^^^^^^
This pluggable client helps dealing with the thundering herd problem. You can read more about it
on link: `Wikipedia <https://en.wikipedia.org/wiki/Thundering_herd_problem>`_
Like previous pluggable clients, it inherits all functionality from the default client, adding some
additional methods for getting/setting keys.
.. code-block:: python
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/1",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.HerdClient",
}
}
}
This client exposes additional settings:
- ``CACHE_HERD_TIMEOUT``: Set default herd timeout. (Default value: 60s)
Pluggable serializer
~~~~~~~~~~~~~~~~~~~~
The pluggable clients serialize data before sending it to the server. By
default, django-redis serializes the data using the Python ``pickle`` module.
This is very flexible and can handle a large range of object types.
To serialize using JSON instead, the serializer ``JSONSerializer`` is also
available.
.. 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",
"SERIALIZER": "django_redis.serializers.json.JSONSerializer",
}
}
}
There's also support for serialization using `MsgPack`_ (that requires the
msgpack library):
.. 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",
"SERIALIZER": "django_redis.serializers.msgpack.MSGPackSerializer",
}
}
}
.. _MsgPack: https://msgpack.org/
Pluggable Redis clientdjango-redis uses the Redis client redis.client.StrictClient by default. It
is possible to use an alternative client.
You can customize the client used by setting REDIS_CLIENT_CLASS in theCACHES setting. Optionally, you can provide arguments to this class by
setting REDIS_CLIENT_KWARGS.
.. code-block:: python
CACHES = {
"default": {
"OPTIONS": {
"REDIS_CLIENT_CLASS": "my.module.ClientClass",
"REDIS_CLIENT_KWARGS": {"some_setting": True},
}
}
}Closing Connections
The default django-redis behavior on close() is to keep the connections to Redis server.
You can change this default behaviour for all caches by the ``DJANGO_REDIS_CLOSE_CONNECTION = True``
in the django settings (globally) or (at cache level) by setting ``CLOSE_CONNECTION: True`` in the ``OPTIONS``
for each configured cache.
Setting True as a value will instruct the django-redis to close all the connections (since v. 4.12.2), irrespectively of its current usage.
.. 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",
"CLOSE_CONNECTION": True,
}
}
}
SSL/TLS and Self-Signed certificatesIn case you encounter a Redis server offering a TLS connection using a
self-signed certificate you may disable certification verification with the
following:
.. code-block:: python
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "rediss://127.0.0.1:6379/1",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"CONNECTION_POOL_KWARGS": {"ssl_cert_reqs": None}
}
}
}License
.. code-block:: text
Copyright (c) 2011-2015 Andrey Antukh <[email protected]>
Copyright (c) 2011 Sean Bleier
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS`` AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.File: AUTHORS.rst
Andrei Antoukh / niwibe https://github.com/niwibe
Sean Bleier https://github.com/sebleier
Matt Dennewitz https://github.com/blackbrrr
Jannis Leidel https://github.com/jezdez
S. Angel / Twidi https://github.com/twidi
Noah Kantrowitz / coderanger https://github.com/coderanger
Martin Mahner / bartTC https://github.com/bartTC
Timothรฉe Peignier / cyberdelia https://github.com/cyberdelia
Lior Sion / liorsion https://github.com/liorsion
Ales Zoulek / aleszoulek https://github.com/aleszoulek
James Aylett / jaylett https://github.com/jaylett
Todd Boland / boland https://github.com/boland
David Zderic / dzderic https://github.com/dzderic
Kirill Zaitsev / teferi https://github.com/teferi
Jon Dufresne https://github.com/jdufresne
Anรจs Foufa https://github.com/AnesFoufa
Segyo Myung https://github.com/myungsegyo
File: CHANGELOG.rst
Changelog
.. towncrier release notes start
django-redis 7.0.0 (2026-06-02)
Features
- Added the ability to pass redis username in the cache options (
#657 <https://github.com/jazzband/django-redis/issues/657>_) RedisCachedoes not attempt to close clients which have not been initialized. (#796 <https://github.com/jazzband/django-redis/issues/796>_)- Add sorted set operations (zadd, zrange, zrem, etc.) and mixins for RedisCache (
#797 <https://github.com/jazzband/django-redis/issues/797>_) - Centralize configuration in
pyproject.toml, drop EoL Python & Django
versions, and add support & testing for modern Python & Django versions. (#820 <https://github.com/jazzband/django-redis/issues/820>_) - Provide TypeVar defaults & provide initial typing for
RedisCache. (#829 <https://github.com/jazzband/django-redis/issues/829>_)
Bug Fixes
- Fix IntEnum encoding (
#602 <https://github.com/jazzband/django-redis/issues/602>_) - Fix incorrect Redis typing that relied on the legacy
types-redispackage, and update the public API to avoid exposing redis-py key types (the encode/decode/make_key methods allow a different API surface). (#822 <https://github.com/jazzband/django-redis/issues/822>_)
Miscellaneous
- Drop support for Django 5.0 (EOL) (
#779 <https://github.com/jazzband/django-redis/issues/779>_) - Clean & organize ruff config (
#781 <https://github.com/jazzband/django-redis/issues/781>_) - Replace black with ruff format (
#782 <https://github.com/jazzband/django-redis/issues/782>_) - Update
RedisCache.closeto not forwardkwargsto the client implementation. (#788 <https://github.com/jazzband/django-redis/issues/788>_) - Rename 'name' parameter to 'key' in all sorted set methods for better consistency with Redis terminology (
#811 <https://github.com/jazzband/django-redis/issues/811>_) - Fix hash method parameters: rename 'name' โ 'key', 'key' โ 'field' to align with Redis/Valkey terminology. Add version parameter to hlen() and hkeys(). Fix make_key() to only apply to hash key, not fields. (
#812 <https://github.com/jazzband/django-redis/issues/812>_) - pre-commit autoupdate (
#819 <https://github.com/jazzband/django-redis/issues/819>_) - Use
from __future__ import annotationsto postpone evaluation of annotations. (#823 <https://github.com/jazzband/django-redis/issues/823>_) - Increase mypy strictness, fix typing configuration, and fix type errors. (
#824 <https://github.com/jazzband/django-redis/issues/824>_) - This change updates the compose configuration, and moves it to
tests
directory as it is only for testing. (#825 <https://github.com/jazzband/django-redis/issues/825>_) - Remove code handling unsupported Django versions (
#826 <https://github.com/jazzband/django-redis/issues/826>_) - Increase mypy type coverage & update strictness overrides to only target specific modules (
#827 <https://github.com/jazzband/django-redis/issues/827>_)
django-redis 6.0.0 (2025-06-17)
Features
- Support HashMaps (
#598 <https://github.com/jazzband/django-redis/issues/598>_) - Support gzip compression (
#688 <https://github.com/jazzband/django-redis/issues/688>_) - Support for sets and support basic operations, sadd, scard, sdiff, sdiffstore, sinter, sinterstore, smismember, sismember, smembers, smove, spop, srandmember, srem, sscan, sscan_iter, sunion, sunionstore (
#730 <https://github.com/jazzband/django-redis/issues/730>_)
Bug Fixes
- Hotfix for timeout=DEFAULT_TIMEOUT in expire and pexpire (
#724 <https://github.com/jazzband/django-redis/issues/724>_) - Fix is_master parsing error for write separation in sentinel mode (
#749 <https://github.com/jazzband/django-redis/issues/749>_) - Added blocking parameter for
cache.lock(#752 <https://github.com/jazzband/django-redis/issues/752>_)
Miscellaneous
- Added support for Python 3.12 (
#689 <https://github.com/jazzband/django-redis/issues/689>_) - Pin pytest to <7.0 until compatibility issues are resolved (
#690 <https://github.com/jazzband/django-redis/issues/690>_) - Replace isort and flake8 with ruff (
#692 <https://github.com/jazzband/django-redis/issues/692>_) - Drop django 4.0 (
#693 <https://github.com/jazzband/django-redis/issues/693>_) - Upgrade black to 23.10.1 (
#695 <https://github.com/jazzband/django-redis/issues/695>_) - Typed DefaultClient (
#696 <https://github.com/jazzband/django-redis/issues/696>_) - Support pytest>=7 (
#697 <https://github.com/jazzband/django-redis/issues/697>_) - Drop support for django 3.2, python 3.6 and python 3.7 (
#699 <https://github.com/jazzband/django-redis/issues/699>_) - Support tox 4 (
#701 <https://github.com/jazzband/django-redis/issues/701>_) - Configured dependabot for github actions (
#702 <https://github.com/jazzband/django-redis/issues/702>_) - Use ubuntu-latest for CI (
#703 <https://github.com/jazzband/django-redis/issues/703>_) - Dropped support for django 4.1 and added support for django 5.0 (
#729 <https://github.com/jazzband/django-redis/issues/729>_) - Added support for django 5.1 (
#754 <https://github.com/jazzband/django-redis/issues/754>_) - Update minimum supported versions in README.md: Python to 3.8, Django to 4.2, redis-py to 4.0.2 (
#755 <https://github.com/jazzband/django-redis/issues/755>_) - Added support for Python 3.13 (
#756 <https://github.com/jazzband/django-redis/issues/756>_) - Speed up tests by using
pytest-xdistand separating settings on different redis databases.
Droppedpytest-django
Usingdocker-composefor setting up redis containers for testing
Usetox-uv(#757 <https://github.com/jazzband/django-redis/issues/757>_) - Confirm support for Django 5.2.
Fix shadowing builtin Python exceptions. (#824 <https://github.com/jazzband/django-redis/issues/824>_)
Deprecations and Removals
- Drop support for Python 3.8 (
#852 <https://github.com/jazzband/django-redis/issues/852>_)
django-redis 5.4.0 (2023-10-01)
Features
- Connection factory goes to cache options (
#680 <https://github.com/jazzband/django-redis/issues/680>_)
Documentation
- Added note in docs for correctly configuring hiredis parser when using redis-py version 5. (
#677 <https://github.com/jazzband/django-redis/issues/677>_)
django-redis 5.3.0 (2023-06-16)
Features
- Add support for django 4 (
#627 <https://github.com/jazzband/django-redis/issues/627>_)
Bug Fixes
- Access
django_redis.cache.DJANGO_REDIS_SCAN_ITERSIZEanddjango_redis.client.herd.CACHE_HERD_TIMEOUTin runtime to not read Django settings in import time. (#638 <https://github.com/jazzband/django-redis/issues/638>_) - Skipping pickle serializer test for django >= 4.2 (
#646 <https://github.com/jazzband/django-redis/issues/646>_)
Miscellaneous
- Speed up deleting multiple keys by a pattern with pipelines and larger itersize (
#609 <https://github.com/jazzband/django-redis/issues/609>_) - Print full exception traceback when logging ignored exceptions (
#611 <https://github.com/jazzband/django-redis/issues/611>_) - Fix mypy linting (
#626 <https://github.com/jazzband/django-redis/issues/626>_) - Added support for python 3.11 (
#633 <https://github.com/jazzband/django-redis/issues/633>_) - Fix CI, running tox<4 to still support Python 3.6. (
#645 <https://github.com/jazzband/django-redis/issues/645>_) - Dropped support for django 2.2 and 3.1 (
#649 <https://github.com/jazzband/django-redis/issues/649>_) - Run actions & tox against Django 4..2 (
#668 <https://github.com/jazzband/django-redis/issues/668>_)
django-redis 5.2.0 (2021-12-22)
Bug Fixes
- Block use with broken redis-py 4.0.0 and 4.0.1 (
#542 <https://github.com/jazzband/django-redis/issues/542>_)
Miscellaneous
- Unblock redis-py >=4.0.2 (
#576 <https://github.com/jazzband/django-redis/issues/576>_) - Add support for django 4 (
#579 <https://github.com/jazzband/django-redis/issues/579>_)
Django_Redis 5.1.0 (2021-11-29)
Features
- Add Python 3.10 to CI (
#536 <https://github.com/jazzband/django-redis/issues/536>_) - Configured
towncrierto generate the changelog. (#548 <https://github.com/jazzband/django-redis/issues/548>_) - Added
django_redis.compressors.zstd.ZStdCompressorto providepyzstdcache value compression. (#551 <https://github.com/jazzband/django-redis/issues/551>_) - Change pickle default version to Python default instead of highest version. (
#555 <https://github.com/jazzband/django-redis/issues/555>_) - Add
hiredisextra dependency to requestredis[hiredis]. (#556 <https://github.com/jazzband/django-redis/issues/556>_) - Add pexpireat to allow setting 'expire at' with millisecond precision. (
#564 <https://github.com/jazzband/django-redis/issues/564>_)
Bug Fixes
- Make expire, pexpire, expireat and persist return the redis client value (
#564 <https://github.com/jazzband/django-redis/issues/564>_)
Miscellaneous
- Convert most unittest class tests to pytest tests. (
#553 <https://github.com/jazzband/django-redis/issues/553>_) - Update type comments to type annotations. (
#568 <https://github.com/jazzband/django-redis/issues/568>_) - Pin redis-py to 3.x until 4.x breaking changes can be addressed. (
#570 <https://github.com/jazzband/django-redis/issues/570>_)
Documentation
- Clarify redis primary name in sentinel documentation. (
#529 <https://github.com/jazzband/django-redis/issues/529>_) - Add documentation on configuring self signed SSL certificates. (
#559 <https://github.com/jazzband/django-redis/issues/559>_)
django-redis 5.0.0 (2021-05-30)
- supporting django 3.1 and django 3.2
- dropped support for python 3.5
- added support for python 3.9
- started type hinting the codebase
- ensure connections are closed
- fixed
ShardClient.clear()method .delete()now returns boolean from django 3.1 onwards- disconnect connection pools on
.close() - added support for redis sentinel
- added
.expire_at()method - fixed
.incr()when ttl isNoneor when the number is larger than 64 bit - fixed
.incr_version()when ttl isNone - added
.pttl()method to the clients to support milli-second precision for
ttl of a key - added
.pexpire()method to the clients to support milli-second precision
for setting expiry of a key
django-redis 4.12.1 (2020-05-27)
- No code changes.
- Fixed a typo in setup.cfg metadata preventing a successful release.
django-redis 4.12.0 (2020-05-27)
- The project has moved to
Jazzband <https://jazzband.co/>. This is the
first release under the new organization. The new repository URL is<https://github.com/jazzband/django-redis>. - Removed support for end-of-life Django < 2.2.
- Removed support for unmaintained redis-py 2.X.
- Changed uses of deprecated
smart_text()tosmart_str(). - Fixed deprecation warning with the msgpack serializer.
- The
.touch()method now uses the default timeout, to cache forever passNone. - Subclasses of
JSONSerializercan now override theencoder_class
attribute to change the JSON encoder. It defaults toDjangoJSONEncoder. - Fixed
DefaultClient.set()to work with emptyPipeline. - The
thread_localparameter is now forwarded to the Redis client.
django-redis 4.11.0 (2019-12-13)
- Removed support for Python 2.7 and 3.4.
- Removed support for Django 2.0 and 2.1.
- Added support for Python 3.8.
- Added support for Django 2.2 and 3.0.
- Changed msgpack-python soft dependency to msgpack.
- Fixed
.touch()method for sharded client. - Fixed prefix escaping for the sharded client.
- Fixed
.add()method to return a bool.
django-redis 4.10.0 (2018-10-19)
- Add support and testing for Django 2.1 and Python 3.7. No actual code changes
were required. - Add support for redis-py 3.0.
- Add touch command.
django-redis 4.9.1 (2018-10-19)
- Pin redis version to 2.10.6
django-redis 4.9.0 (2018-03-01)
- Add testing and support for Django 2.0. No actual code changes were required.
- Escape
KEY_PREFIXandVERSIONwhen used in glob expressions. - Improve handling timeouts less than 1ms.
- Remove fakeredis support.
- Add datetime, date, time, and timedelta serialization support to the JSON
serializer. - The deprecated feature of passing
Trueas a timeout value is no longer
supported. - Fix
add()with a negative timeout to not store key (it is immediately
invalid). - Remove support for Django < 1.11.
- Add support for atomic incr if key is not set.
django-redis 4.8.0 (2017-04-25)
- Drop deprecated exception with typo ConnectionInterrumped. Use
ConnectionInterrupted instead. - Remove many workarounds related to old and not supported versions
of django and redis-py. - Code cleaning and flake8 compliance fixes.
- Add better impl for
closemethod. - Fix compatibility warnings with python 3.6
django-redis 4.7.0 (2017-01-02)
- Add the ability to enable write to replica servers when the primary server is
not available. - Add
itersizeparameter todelete_pattern.
django-redis 4.6.0 (2016-11-02)
- Fix incorrect behavior of
clear()method.
django-redis 4.5.0 (2016-09-21)
- Now only support Django 1.8 and above. Support for older versions has been dropped.
- Remove undocumented and deprecated support for old connection string format.
- Add support for
PASSWORDoption (useful when the password contains url unsafe
characters). - Make the package compatible with fake redis.
- Fix compatibility issues with latest django version (1.10).
django-redis 4.4.4 (2016-07-25)
- Fix possible race condition on incr implementation using
lua script (thanks to @prokaktus).
django-redis 4.4.3 (2016-05-17)
- Fix minor ttl inconsistencies.
django-redis 4.4.2 (2016-04-21)
- Fix timeout bug (thanks to @skorokithakis)
django-redis 4.4.1 (2016-04-13)
- Add additional check for avoid wrong exception on
get_redis_connection.
django-redis 4.4.0 (2016-04-12)
- Make redis client pluggable (thanks to @arnuschky)
- Add version number inside python module (thanks to @BertrandBordage)
- Fix clear method (thanks to @ostcar)
- Add the ability to specify key prefix on delete and delete_pattern.
- BREAKING CHANGE: improved compression support (make it more plugable).
django-redis 4.3.0 (2015-10-31)
- Improved exception handling in herd client (thanks to @brandoshmando)
- Fix bug that not allows use generators on delete_many (thanks to @ostcar).
- Remove obsolete code that makes hard dependency to mspack.
django-redis 4.2.0 (2015-07-03)
- Add
persistandexpiremethods. - Remove old and broken dummy client.
- Expose a redis lock method.
django-redis 4.1.0 (2015-06-15)
- Add plugable serializers architecture (thanks to @jdufresne)
- Add json serializer (thanks to @jdufresne)
- Add msgpack serializer (thanks to @uditagarwal)
- Implement delete_pattern using iter_scan for better performance (thanks to @lenzenmi)
django-redis 4.0.0
- Remove usage of deprecated
get_cachemethod. - Added connection option SOCKET_CONNECT_TIMEOUT. [Jorge C. Leitรฃo].
- Replace
setexand friends with set, because it now supports all need for atomic.
updates (thanks to @23doors) (re revert changes from 3.8.x branch). - Fix django 1.8 compatibilities.
- Fix django 1.9 compatibilities.
- BREAKING CHANGE: Now timeout=0 works as django specified (expires immediately)
- Now requires redis server >= 2.8
- BREAKING CHANGE:
redis_cacheis no longer a valid package name
django-redis 3.8.4
- Backport django 1.8 fixes from master.
django-redis 3.8.3
- Minor fix on regular expression for old url notation.
django-redis 3.8.2
- Revert some changes from 3.8.1 that are incompatible with redis server < 2.6.12
django-redis 3.8.1
- Fix documentation related to new url format.
- Fix documentation parts that uses now removed functions.
- Fix invalid url transformation from old format (password was not set properly)
- Replace setex and friends with set, because it now supports all need for atomic
updates (thanks to @23doors).
django-redis 3.8.0
- Add compression support. (Thanks to @alanjds)
- Change package name from redis_cache to django_redis.
- Add backward compatibility layer for redis_cache package name.
- BACKWARD INCOMPATIBLE CHANGE: use StrictRedis instead of Redis class of redis-py
- Add redis dummy backend for development purposes. (Thanks to @papaloizouc)
- Now use redis native url notation for connection string (the own connection string
notation is also supported but is marked as deprecated). - Now requires redis-py >= 2.10.0
- Remove deprecated
raw_cacheproperty from backend.
django-redis 3.7.2
- Add missing forward of version parameter from
add()toset()function. (by @fellowshipofone)
django-redis 3.7.1
- Improve docs (by @dkingman).
- Fix missing imports on sentinel client (by @opapy).
- Connection closing improvements on sentinel client (by @opapy).
django-redis 3.7.0
- Add support for django's
KEY_FUNCTIONandREVERSE_KEY_FUNCTION(by @teferi) - Accept float value for socket timeout.
- Fix wrong behavior of
DJANGO_REDIS_IGNORE_EXCEPTIONSwith socket timeouts. - Backward incompatible change: now raises original exceptions instead of self defined.
django-redis 3.6.2
- Add ttl method purposed to be included in django core.
- Add iter_keys method that uses redis scan methods for memory efficient keys retrieval.
- Add version keyword parameter to keys.
- Deprecate django 1.3.x support.
django-redis 3.6.1
- Fix wrong import on sentinel client.
django-redis 3.6.0
- Add pluggable connection factory.
- Negative timeouts now works as expected.
- Delete operation now returns a number of deleted items instead of None.
django-redis 3.5.1
- Fixed redis-py < 2.9.0 incompatibilities
- Fixed runtests error with django 1.7
django-redis 3.5.0
- Removed: stats module (should be replaced with an other in future)
- New: experimental client for add support to redis-sentinel.
- Now uses a django
DEFAULT_TIMEOUTconstant instead ofTrue.
Deprecation warning added for code that now usesTrue(unlikely). - Fix wrong forward of timeout on shard client.
- Fix incr_version wrong behavior when using shard client (wrong client used for set new key).
django-redis 3.4.0
Fix exception name from ConnectionInterrumped to
ConnectionInterrupted maintaining an old exception class
for backward compatibility (thanks ลukasz Langa (@ambv))Fix wrong behavior for "default" parameter on get method
when DJANGO_REDIS_IGNORE_EXCEPTIONS is True
(also thanks to ลukasz Langa (@ambv)).Now added support for replication setups to default client (it still
experimental because is not tested in production environments).Merged SimpleFailoverClient experimental client (only for
experiment with it, not ready for use in production)Django 1.6 cache changes compatibility. Explicitly passing in
timeout=None no longer results in using the default timeout.Major code cleaning. (Thanks to Bertrand Bordage @BertrandBordage)
Bugfixes related to some index error on hashring module.
django-redis 3.3.0
- Add SOCKET_TIMEOUT attribute to OPTIONS (thanks to @eclipticplane)
django-redis 3.2.0
- Changed default behavior of connection error exceptions: now by default
raises exception on connection error is occurred.
Thanks to Mรผmin รztรผrk:
- cache.add now uses setnx redis command (atomic operation)
- cache.incr and cache.decr now uses redis incrby command (atomic operation)
django-redis 3.1.7
- Fix python3 compatibility on utils module.
django-redis 3.1.6
- Add nx argument on set method for both clients (thanks to Kirill Zaitsev)
django-redis 3.1.5
- Bug fixes on sharded client.
django-redis 3.1.4
- Now reuse connection pool on massive use of
get_cachemethod.
django-redis 3.1.3
- Fixed python 2.6 compatibility.
django-redis 3.1.2
- Now on call close() not disconnect all connection pool.
django-redis 3.1.1
- Fixed incorrect exception message on LOCATION has wrong format.
(Thanks to Yoav Weiss)
django-redis 3.1
- Helpers for access to raw redis connection.
django-redis 3.0
- Python 3.2+ support.
- Code cleaning and refactor.
- Ignore exceptions (same behavior as memcached backend)
- Pluggable clients.
- Unified connection string.
django-redis 2.2.2
- Bug fixes on
keysanddelete_patternmethods.
django-redis 2.2.1
- Remove duplicate check if key exists on
incrmethod. - Fix incorrect behavior of
delete_patternwith sharded client.
django-redis 2.2
- New
delete_patternmethod. Useful for delete keys using wildcard syntax.
django-redis 2.1
- Many bug fixes.
- Client side sharding.
File: CODE_OF_CONDUCT.md
Code of Conduct
As contributors and maintainers of the Jazzband projects, and in the interest of
fostering an open and welcoming community, we pledge to respect all people who
contribute through reporting issues, posting feature requests, updating documentation,
submitting pull requests or patches, and other activities.
We are committed to making participation in the Jazzband a harassment-free experience
for everyone, regardless of the level of experience, gender, gender identity and
expression, sexual orientation, disability, personal appearance, body size, race,
ethnicity, age, religion, or nationality.
Examples of unacceptable behavior by participants include:
- The use of sexualized language or imagery
- Personal attacks
- Trolling or insulting/derogatory comments
- Public or private harassment
- Publishing other's private information, such as physical or electronic addresses,
without explicit permission - Other unethical or unprofessional conduct
The Jazzband roadies have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are not
aligned to this Code of Conduct, or to ban temporarily or permanently any contributor
for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
By adopting this Code of Conduct, the roadies commit themselves to fairly and
consistently applying these principles to every aspect of managing the jazzband
projects. Roadies who do not follow or enforce the Code of Conduct may be permanently
removed from the Jazzband roadies.
This code of conduct applies both within project spaces and in public spaces when an
individual is representing the project or its community.
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by
contacting the roadies at [email protected]. All complaints will be reviewed and
investigated and will result in a response that is deemed necessary and appropriate to
the circumstances. Roadies are obligated to maintain confidentiality with regard to the
reporter of an incident.
This Code of Conduct is adapted from the Contributor Covenant, version
1.3.0, available at https://contributor-covenant.org/version/1/3/0/
File: CONTRIBUTING.rst
.. image:: https://jazzband.co/static/img/jazzband.svg
:target: https://jazzband.co/
:alt: Jazzband
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>_.
File: RELEASING.rst
Preparing a Release
The following steps are needed to prepare a release:
- Make sure the VERSION in
django_redis/__init__.pyhas been updated. - Run
towncrier buildto update theCHANGELOG.rstwith the
news fragments for the release. - Commit the changes for steps 1 and 2.
- Tag the commit with the same version as specified for VERSION in step 1.
- Wait for the
release action_ to complete, which will upload the package
todjango-redis jazzband_, and when it's complete you can then release
the package to PyPI.
.. _release action: https://github.com/jazzband/django-redis/actions/workflows/release.yml
.. _django-redis jazzband: https://jazzband.co/projects/django-redis
File: .pre-commit-config.yaml
repos:
repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:- id: check-ast
- id: check-case-conflict
- id: check-docstring-first
- id: check-merge-conflict
- id: check-symlinks
- id: debug-statements
repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.15.15
hooks:- id: ruff-check
args: [ --fix, --exit-non-zero-on-fix , --show-fixes] - id: ruff-format
- id: ruff-check
File: tests/README.rst
Running the test suite
.. code-block:: bash
start redis and a sentinel (uses docker with image redis:alpine)
docker compose -f tests/compose.yml up --detach --wait
File: tests/compose.yml
services:
redis:
image: redis:alpine
healthcheck:
test: ['CMD', 'redis-cli', 'ping']
start_period: 1m
start_interval: 1s
ports:
- 6379:6379
redis-sentinel:
command:
# Force sh as the shell as the multiline quoted string below is not
# being written correctly, and it's not clear what shell is being run.
- sh
- -c
# Generate a sentinel configuration that is writable by the sentinel
- |
echo '
sentinel resolve-hostnames yes
sentinel monitor redis redis 6379 1
sentinel down-after-milliseconds redis 3200
sentinel failover-timeout redis 10000
sentinel parallel-syncs redis 1
' > /etc/redis-sentinel.conf
exec redis-server /etc/redis-sentinel.conf --sentinel
depends_on:
redis:
condition: service_healthy
image: redis:alpine
healthcheck:
test: ['CMD', 'redis-cli', '-p', '26379', 'ping']
start_period: 1m
start_interval: 1s
ports:
- 26379:26379File: .github/codecov.yml
coverage:
small changes should not fail coverage
precision: 1
round: up
status:
project:
default:
target: auto
mypy:
target: auto
flags:
- mypy
tests:
target: auto
flags:
- testsFile: .github/dependabot.yml
To get started with Dependabot version updates, you'll need to specify which
package ecosystems to update and where the package manifests are located.
Please see the documentation for all configuration options:
https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/" # Location of package manifests
schedule:
interval: "daily"
File: .github/ISSUE_TEMPLATE/bug_report.md
name: Bug report
about: Create a report to help us improve
labels: bug
Describe the bug
A clear and concise description of what the bug is.
To Reproduce
Steps to reproduce the behavior:
- Go to '...'
- Click on '....'
- Scroll down to '....'
- See error
Expected behavior
A clear and concise description of what you expected to happen.
Stack trace
If applicable, add stack trace to help explain your problem.
Environment (please complete the following information):
- Python version: [e.g. 3.5]
- Django Redis Version: [e.g. 1.9.1]
- Django Version: [e.g. 1.11.11]
- Redis Version: [e.g. 2.5.0]
- redis-py Version: [e.g. 3.5.0]
Additional context
Add any other context about the problem here.
File: .github/ISSUE_TEMPLATE/feature_request.md
name: Feature request
about: Suggest an idea for this project
Problem Statement
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
Describe the solution you'd like
A clear and concise description of what you want to happen.
Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.
Additional context
Add any other context or screenshots about the feature request here.
File: .github/ISSUE_TEMPLATE/question.md
name: Question
about: Create question to us
title: ''
labels: question
assignees: ''
File: .github/workflows/ci.yml
name: CI
on: [push, pull_request]
jobs:
test:
name: >
Test Python ${{ matrix.python-version }},
Django ${{ matrix.django-version }},
Redis.py ${{ matrix.redis-version }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version:
- '3.12'
- '3.13'
- '3.14'
django-version:
- '5.2'
- '6.0'
redis-version:
- 'latest'
include:
# Django 5.2 supports Python 3.10 & Python 3.11
- python-version: '3.10'
django-version: '5.2'
- python-version: '3.11'
django-version: '5.2'
# Only test pre-release dependencies for the latest Python.
# latest Django with pre-release redis
- python-version: '3.14'
django-version: '6.0'
redis-version: 'master'
# pre-release Django with latest redis
- python-version: '3.14'
django-version: 'main'
redis-version: 'latest'
# pre-release Django and pre-release redis
- python-version: '3.14'
django-version: 'main'
redis-version: 'master'
steps:
- uses: actions/checkout@v6
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
- name: Get pip cache dir
id: pip-cache
run: |
echo "::set-output name=dir::$(pip cache dir)"
- name: Cache
uses: actions/cache@v5
with:
path: ${{ steps.pip-cache.outputs.dir }}
key: pip-test-python-${{ matrix.python-version }}-django-${{ matrix.django-version }}-redis-${{ matrix.redis-version }}-${{ hashFiles('**/pyproject.toml') }}
restore-keys: |
pip-test-python-${{ matrix.python-version }}-django-${{ matrix.django-version }}-redis-${{ matrix.redis-version }}
pip-test-python-${{ matrix.python-version }}
pip-test-
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install --upgrade tox-uv tox-gh
- name: Docker compose up
run: docker compose -f tests/compose.yml up --detach --wait
- name: Tox tests
run: tox
env:
DJANGO: ${{ matrix.django-version }}
REDIS: ${{ matrix.redis-version }}
- name: Docker compose down
if: ${{ !cancelled() }}
run: docker compose -f tests/compose.yml down
- name: Upload coverage
uses: codecov/codecov-action@v7
with:
env_vars: DJANGO,REDIS,PYTHON
flags: tests
env:
DJANGO: ${{ matrix.django-version }}
REDIS: ${{ matrix.redis-version }}
PYTHON: ${{ matrix.python-version }} lint:
name: Lint (${{ matrix.tool }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
tool:
- 'pre-commit'
- 'mypy'
steps:
- uses: actions/checkout@v6
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.x'
- name: Get pip cache dir
id: pip-cache
run: |
echo "::set-output name=dir::$(pip cache dir)"
- name: Cache
uses: actions/cache@v5
with:
path: ${{ steps.pip-cache.outputs.dir }}
key: pip-lint-${{ hashFiles('**/pyproject.toml') }}
restore-keys: |
pip-lint-
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install --upgrade tox
- name: Run ${{ matrix.tool }}
run: tox -e ${{ matrix.tool }}
- name: Upload coverage
if: ${{ matrix.tool == 'mypy' }}
uses: codecov/codecov-action@v7
with:
flags: mypy check-changelog:
name: Check for news fragments in 'changelog.d/'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.x'
- name: Get pip cache dir
id: pip-cache
run: |
echo "::set-output name=dir::$(pip cache dir)"
- name: Cache
uses: actions/cache@v5
with:
path: ${{ steps.pip-cache.outputs.dir }}
key: pip-check-changelog-${{ hashFiles('**/pyproject.toml') }}
restore-keys: |
pip-check-changelog-
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install --upgrade towncrier
- name: Run towncrier check
run: |
if ! towncrier check; then
echo ''
echo "Please add a description of your changes to 'changelog.d/{issue or PR number}.{feature,bugfix,misc,doc,removal}'"
exit 1
fiFile: .github/workflows/release.yml
name: Release
on:
push:
tags:
- '*'
jobs:
build:
if: github.repository == 'jazzband/django-redis'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: 3.9
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install --upgrade build twine
- name: Build package
run: |
python -m build
twine check dist/*
- name: Upload packages to Jazzband
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
uses: pypa/gh-action-pypi-publish@master
with:
user: jazzband
password: ${{ secrets.JAZZBAND_RELEASE_KEY }}
repository_url: https://jazzband.co/projects/django-redis/upload