1Metadata-Version: 2.1
2Name: django-redis
3Version: 5.1.0
4Summary: Full featured redis cache backend for Django.
5Home-page: https://github.com/jazzband/django-redis
6Author: Andrei Antoukh
7Author-email: niwi@niwi.nz
8License: BSD-3-Clause
9Platform: UNKNOWN
10Classifier: Development Status :: 5 - Production/Stable
11Classifier: Environment :: Web Environment
12Classifier: Framework :: Django
13Classifier: Framework :: Django :: 2.2
14Classifier: Framework :: Django :: 3.1
15Classifier: Framework :: Django :: 3.2
16Classifier: Intended Audience :: Developers
17Classifier: License :: OSI Approved :: BSD License
18Classifier: Operating System :: OS Independent
19Classifier: Programming Language :: Python
20Classifier: Programming Language :: Python :: 3
21Classifier: Programming Language :: Python :: 3 :: Only
22Classifier: Programming Language :: Python :: 3.6
23Classifier: Programming Language :: Python :: 3.7
24Classifier: Programming Language :: Python :: 3.8
25Classifier: Programming Language :: Python :: 3.9
26Classifier: Programming Language :: Python :: 3.10
27Classifier: Topic :: Software Development :: Libraries
28Classifier: Topic :: Utilities
29Requires-Python: >=3.6
30Description-Content-Type: text/x-rst
31Provides-Extra: hiredis
32License-File: LICENSE
33License-File: AUTHORS.rst
34
35==============================
36Redis cache backend for Django
37==============================
38
39.. image:: https://jazzband.co/static/img/badge.svg
40    :target: https://jazzband.co/
41    :alt: Jazzband
42
43.. image:: https://github.com/jazzband/django-redis/actions/workflows/ci.yml/badge.svg
44   :target: https://github.com/jazzband/django-redis/actions/workflows/ci.yml
45   :alt: GitHub Actions
46
47.. image:: https://codecov.io/gh/jazzband/django-redis/branch/master/graph/badge.svg
48   :target: https://codecov.io/gh/jazzband/django-redis
49   :alt: Coverage
50
51.. image:: https://img.shields.io/pypi/v/django-redis.svg?style=flat
52    :target: https://pypi.org/project/django-redis/
53
54This is a `Jazzband <https://jazzband.co>`_ project. By contributing you agree
55to abide by the `Contributor Code of Conduct
56<https://jazzband.co/about/conduct>`_ and follow the `guidelines
57<https://jazzband.co/about/guidelines>`_.
58
59Introduction
60------------
61
62django-redis is a BSD licensed, full featured Redis cache and session backend
63for Django.
64
65Why use django-redis?
66~~~~~~~~~~~~~~~~~~~~~
67
68- Uses native redis-py url notation connection strings
69- Pluggable clients
70- Pluggable parsers
71- Pluggable serializers
72- Primary/secondary support in the default client
73- Comprehensive test suite
74- Used in production in several projects as cache and session storage
75- Supports infinite timeouts
76- Facilities for raw access to Redis client/connection pool
77- Highly configurable (can emulate memcached exception behavior, for example)
78- Unix sockets supported by default
79
80Requirements
81~~~~~~~~~~~~
82
83- `Python`_ 3.6+
84- `Django`_ 2.2+
85- `redis-py`_ 3.0+
86- `Redis server`_ 2.8+
87
88.. _Python: https://www.python.org/downloads/
89.. _Django: https://www.djangoproject.com/download/
90.. _redis-py: https://pypi.org/project/redis/
91.. _Redis server: https://redis.io/download
92
93User guide
94----------
95
96Installation
97~~~~~~~~~~~~
98
99Install with pip:
100
101.. code-block:: console
102
103    $ python -m pip install django-redis
104
105Configure as cache backend
106~~~~~~~~~~~~~~~~~~~~~~~~~~
107
108To start using django-redis, you should change your Django cache settings to
109something like:
110
111.. code-block:: python
112
113    CACHES = {
114        "default": {
115            "BACKEND": "django_redis.cache.RedisCache",
116            "LOCATION": "redis://127.0.0.1:6379/1",
117            "OPTIONS": {
118                "CLIENT_CLASS": "django_redis.client.DefaultClient",
119            }
120        }
121    }
122
123django-redis uses the redis-py native URL notation for connection strings, it
124allows better interoperability and has a connection string in more "standard"
125way. Some examples:
126
127- ``redis://[[username]:[password]]@localhost:6379/0``
128- ``rediss://[[username]:[password]]@localhost:6379/0``
129- ``unix://[[username]:[password]]@/path/to/socket.sock?db=0``
130
131Three URL schemes are supported:
132
133- ``redis://``: creates a normal TCP socket connection
134- ``rediss://``: creates a SSL wrapped TCP socket connection
135- ``unix://`` creates a Unix Domain Socket connection
136
137There are several ways to specify a database number:
138
139- A ``db`` querystring option, e.g. ``redis://localhost?db=0``
140- If using the ``redis://`` scheme, the path argument of the URL, e.g.
141  ``redis://localhost/0``
142
143When using `Redis' ACLs <https://redis.io/topics/acl>`_, you will need to add the
144username to the URL (and provide the password with the Cache ``OPTIONS``).
145The login for the user ``django`` would look like this:
146
147.. code-block:: python
148
149    CACHES = {
150        "default": {
151            "BACKEND": "django_redis.cache.RedisCache",
152            "LOCATION": "redis://django@localhost:6379/0",
153            "OPTIONS": {
154                "CLIENT_CLASS": "django_redis.client.DefaultClient",
155                "PASSWORD": "mysecret"
156            }
157        }
158    }
159
160An alternative would be write both username and password into the URL:
161
162.. code-block:: python
163
164    CACHES = {
165        "default": {
166            "BACKEND": "django_redis.cache.RedisCache",
167            "LOCATION": "redis://django:mysecret@localhost:6379/0",
168            "OPTIONS": {
169                "CLIENT_CLASS": "django_redis.client.DefaultClient",
170            }
171        }
172    }
173
174In some circumstances the password you should use to connect Redis
175is not URL-safe, in this case you can escape it or just use the
176convenience option in ``OPTIONS`` dict:
177
178.. code-block:: python
179
180    CACHES = {
181        "default": {
182            "BACKEND": "django_redis.cache.RedisCache",
183            "LOCATION": "redis://127.0.0.1:6379/1",
184            "OPTIONS": {
185                "CLIENT_CLASS": "django_redis.client.DefaultClient",
186                "PASSWORD": "mysecret"
187            }
188        }
189    }
190
191Take care, that this option does not overwrites the password in the uri, so if
192you have set the password in the uri, this settings will be ignored.
193
194Configure as session backend
195~~~~~~~~~~~~~~~~~~~~~~~~~~~~
196
197Django can by default use any cache backend as session backend and you benefit
198from that by using django-redis as backend for session storage without
199installing any additional backends:
200
201.. code-block:: python
202
203    SESSION_ENGINE = "django.contrib.sessions.backends.cache"
204    SESSION_CACHE_ALIAS = "default"
205
206Testing with django-redis
207~~~~~~~~~~~~~~~~~~~~~~~~~
208
209django-redis supports customizing the underlying Redis client (see "Pluggable
210clients"). This can be used for testing purposes.
211
212In case you want to flush all data from the cache after a test, add the
213following lines to your test class:
214
215.. code-block:: python
216
217    from django_redis import get_redis_connection
218
219    def tearDown(self):
220        get_redis_connection("default").flushall()
221
222Advanced usage
223--------------
224
225Pickle version
226~~~~~~~~~~~~~~
227
228For almost all values, django-redis uses pickle to serialize objects.
229
230The ``pickle.DEFAULT_PROTOCOL`` version of pickle is used by default to ensure safe upgrades and compatibility across Python versions.
231If you want set a concrete version, you can do it, using ``PICKLE_VERSION`` option:
232
233.. code-block:: python
234
235    CACHES = {
236        "default": {
237            # ...
238            "OPTIONS": {
239                "PICKLE_VERSION": -1  # Will use highest protocol version available
240            }
241        }
242    }
243
244Socket timeout
245~~~~~~~~~~~~~~
246
247Socket timeout can be set using ``SOCKET_TIMEOUT`` and
248``SOCKET_CONNECT_TIMEOUT`` options:
249
250.. code-block:: python
251
252    CACHES = {
253        "default": {
254            # ...
255            "OPTIONS": {
256                "SOCKET_CONNECT_TIMEOUT": 5,  # seconds
257                "SOCKET_TIMEOUT": 5,  # seconds
258            }
259        }
260    }
261
262``SOCKET_CONNECT_TIMEOUT`` is the timeout for the connection to be established
263and ``SOCKET_TIMEOUT`` is the timeout for read and write operations after the
264connection is established.
265
266Compression support
267~~~~~~~~~~~~~~~~~~~
268
269django-redis comes with compression support out of the box, but is deactivated
270by default. You can activate it setting up a concrete backend:
271
272.. code-block:: python
273
274    CACHES = {
275        "default": {
276            # ...
277            "OPTIONS": {
278                "COMPRESSOR": "django_redis.compressors.zlib.ZlibCompressor",
279            }
280        }
281    }
282
283Let see an example, of how make it work with *lzma* compression format:
284
285.. code-block:: python
286
287    import lzma
288
289    CACHES = {
290        "default": {
291            # ...
292            "OPTIONS": {
293                "COMPRESSOR": "django_redis.compressors.lzma.LzmaCompressor",
294            }
295        }
296    }
297
298*Lz4* compression support (requires the lz4 library):
299
300.. code-block:: python
301
302    import lz4
303
304    CACHES = {
305        "default": {
306            # ...
307            "OPTIONS": {
308                "COMPRESSOR": "django_redis.compressors.lz4.Lz4Compressor",
309            }
310        }
311    }
312
313*Zstandard (zstd)* compression support (requires the pyzstd library):
314
315.. code-block:: python
316
317    import pyzstd
318
319    CACHES = {
320        "default": {
321            # ...
322            "OPTIONS": {
323                "COMPRESSOR": "django_redis.compressors.zstd.ZStdCompressor",
324            }
325        }
326    }
327
328Memcached exceptions behavior
329~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
330
331In some situations, when Redis is only used for cache, you do not want
332exceptions when Redis is down. This is default behavior in the memcached
333backend and it can be emulated in django-redis.
334
335For setup memcached like behaviour (ignore connection exceptions), you should
336set ``IGNORE_EXCEPTIONS`` settings on your cache configuration:
337
338.. code-block:: python
339
340    CACHES = {
341        "default": {
342            # ...
343            "OPTIONS": {
344                "IGNORE_EXCEPTIONS": True,
345            }
346        }
347    }
348
349Also, you can apply the same settings to all configured caches, you can set the global flag in
350your settings:
351
352.. code-block:: python
353
354    DJANGO_REDIS_IGNORE_EXCEPTIONS = True
355
356Log Ignored Exceptions
357~~~~~~~~~~~~~~~~~~~~~~
358
359When ignoring exceptions with ``IGNORE_EXCEPTIONS`` or
360``DJANGO_REDIS_IGNORE_EXCEPTIONS``, you may optionally log exceptions using the
361global variable ``DJANGO_REDIS_LOG_IGNORED_EXCEPTIONS`` in your settings file::
362
363    DJANGO_REDIS_LOG_IGNORED_EXCEPTIONS = True
364
365If you wish to specify the logger in which the exceptions are output, simply
366set the global variable ``DJANGO_REDIS_LOGGER`` to the string name and/or path
367of the desired logger. This will default to ``__name__`` if no logger is
368specified and ``DJANGO_REDIS_LOG_IGNORED_EXCEPTIONS`` is ``True``::
369
370    DJANGO_REDIS_LOGGER = 'some.specified.logger'
371
372Infinite timeout
373~~~~~~~~~~~~~~~~
374
375django-redis comes with infinite timeouts support out of the box. And it
376behaves in same way as django backend contract specifies:
377
378- ``timeout=0`` expires the value immediately.
379- ``timeout=None`` infinite timeout
380
381.. code-block:: python
382
383    cache.set("key", "value", timeout=None)
384
385Get ttl (time-to-live) from key
386~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
387
388With Redis, you can access to ttl of any stored key, for it, django-redis
389exposes ``ttl`` function.
390
391It returns:
392
393- 0 if key does not exists (or already expired).
394- None for keys that exists but does not have any expiration.
395- ttl value for any volatile key (any key that has expiration).
396
397.. code-block:: pycon
398
399    >>> from django.core.cache import cache
400    >>> cache.set("foo", "value", timeout=25)
401    >>> cache.ttl("foo")
402    25
403    >>> cache.ttl("not-existent")
404    0
405
406With Redis, you can access to ttl of any stored key in milliseconds, for it, django-redis
407exposes ``pttl`` function.
408
409.. code-block:: pycon
410
411    >>> from django.core.cache import cache
412    >>> cache.set("foo", "value", timeout=25)
413    >>> cache.pttl("foo")
414    25000
415    >>> cache.pttl("not-existent")
416    0
417
418Expire & Persist
419~~~~~~~~~~~~~~~~
420
421Additionally to the simple ttl query, you can send persist a concrete key or
422specify a new expiration timeout using the ``persist`` and ``expire`` methods:
423
424.. code-block:: pycon
425
426    >>> cache.set("foo", "bar", timeout=22)
427    >>> cache.ttl("foo")
428    22
429    >>> cache.persist("foo")
430    True
431    >>> cache.ttl("foo")
432    None
433
434.. code-block:: pycon
435
436    >>> cache.set("foo", "bar", timeout=22)
437    >>> cache.expire("foo", timeout=5)
438    True
439    >>> cache.ttl("foo")
440    5
441
442The ``expire_at`` method can be used to make the key expire at a specific moment in time.
443
444.. code-block:: pycon
445
446    >>> cache.set("foo", "bar", timeout=22)
447    >>> cache.expire_at("foo", datetime.now() + timedelta(hours=1))
448    True
449    >>> cache.ttl("foo")
450    3600
451
452The ``pexpire_at`` method can be used to make the key expire at a specific moment in time with milliseconds precision:
453
454.. code-block:: pycon
455
456    >>> cache.set("foo", "bar", timeout=22)
457    >>> cache.pexpire_at("foo", datetime.now() + timedelta(milliseconds=900, hours=1))
458    True
459    >>> cache.ttl("foo")
460    3601
461    >>> cache.pttl("foo")
462    3600900
463
464The ``pexpire`` method can be used to provide millisecond precision:
465
466.. code-block:: pycon
467
468    >>> cache.set("foo", "bar", timeout=22)
469    >>> cache.pexpire("foo", timeout=5500)
470    True
471    >>> cache.pttl("foo")
472    5500
473
474Locks
475~~~~~
476
477It also supports the Redis ability to create Redis distributed named locks. The
478Lock interface is identical to the ``threading.Lock`` so you can use it as
479replacement.
480
481.. code-block:: python
482
483    with cache.lock("somekey"):
484        do_some_thing()
485
486Scan & Delete keys in bulk
487~~~~~~~~~~~~~~~~~~~~~~~~~~
488
489django-redis comes with some additional methods that help with searching or
490deleting keys using glob patterns.
491
492.. code-block:: pycon
493
494    >>> from django.core.cache import cache
495    >>> cache.keys("foo_*")
496    ["foo_1", "foo_2"]
497
498A simple search like this will return all matched values. In databases with a
499large number of keys this isn't suitable method. Instead, you can use the
500``iter_keys`` function that works like the ``keys`` function but uses Redis
501server side cursors. Calling ``iter_keys`` will return a generator that you can
502then iterate over efficiently.
503
504.. code-block:: pycon
505
506    >>> from django.core.cache import cache
507    >>> cache.iter_keys("foo_*")
508    <generator object algo at 0x7ffa9c2713a8>
509    >>> next(cache.iter_keys("foo_*"))
510    "foo_1"
511
512For deleting keys, you should use ``delete_pattern`` which has the same glob
513pattern syntax as the ``keys`` function and returns the number of deleted keys.
514
515.. code-block:: pycon
516
517    >>> from django.core.cache import cache
518    >>> cache.delete_pattern("foo_*")
519
520Redis native commands
521~~~~~~~~~~~~~~~~~~~~~
522
523django-redis has limited support for some Redis atomic operations, such as the
524commands ``SETNX`` and ``INCR``.
525
526You can use the ``SETNX`` command through the backend ``set()`` method with the
527``nx`` parameter:
528
529.. code-block:: pycon
530
531    >>> from django.core.cache import cache
532    >>> cache.set("key", "value1", nx=True)
533    True
534    >>> cache.set("key", "value2", nx=True)
535    False
536    >>> cache.get("key")
537    "value1"
538
539Also, the ``incr`` and ``decr`` methods use Redis atomic operations when the
540value that a key contains is suitable for it.
541
542Raw client access
543~~~~~~~~~~~~~~~~~
544
545In some situations your application requires access to a raw Redis client to
546use some advanced features that aren't exposed by the Django cache interface.
547To avoid storing another setting for creating a raw connection, django-redis
548exposes functions with which you can obtain a raw client reusing the cache
549connection string: ``get_redis_connection(alias)``.
550
551.. code-block:: pycon
552
553    >>> from django_redis import get_redis_connection
554    >>> con = get_redis_connection("default")
555    >>> con
556    <redis.client.Redis object at 0x2dc4510>
557
558WARNING: Not all pluggable clients support this feature.
559
560Connection pools
561~~~~~~~~~~~~~~~~
562
563Behind the scenes, django-redis uses the underlying redis-py connection pool
564implementation, and exposes a simple way to configure it. Alternatively, you
565can directly customize a connection/connection pool creation for a backend.
566
567The default redis-py behavior is to not close connections, recycling them when
568possible.
569
570Configure default connection pool
571^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
572
573The default connection pool is simple. For example, you can customize the
574maximum number of connections in the pool by setting ``CONNECTION_POOL_KWARGS``
575in the ``CACHES`` setting:
576
577.. code-block:: python
578
579    CACHES = {
580        "default": {
581            "BACKEND": "django_redis.cache.RedisCache",
582            # ...
583            "OPTIONS": {
584                "CONNECTION_POOL_KWARGS": {"max_connections": 100}
585            }
586        }
587    }
588
589You can verify how many connections the pool has opened with the following
590snippet:
591
592.. code-block:: python
593
594    from django_redis import get_redis_connection
595
596    r = get_redis_connection("default")  # Use the name you have defined for Redis in settings.CACHES
597    connection_pool = r.connection_pool
598    print("Created connections so far: %d" % connection_pool._created_connections)
599
600Since the default connection pool passes all keyword arguments it doesn't use
601to its connections, you can also customize the connections that the pool makes
602by adding those options to ``CONNECTION_POOL_KWARGS``:
603
604.. code-block:: python
605
606    CACHES = {
607        "default": {
608            # ...
609            "OPTIONS": {
610                "CONNECTION_POOL_KWARGS": {"max_connections": 100, "retry_on_timeout": True}
611            }
612        }
613    }
614
615Use your own connection pool subclass
616^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
617
618Sometimes you want to use your own subclass of the connection pool. This is
619possible with django-redis using the ``CONNECTION_POOL_CLASS`` parameter in the
620backend options.
621
622.. code-block:: python
623
624    from redis.connection import ConnectionPool
625
626    class MyOwnPool(ConnectionPool):
627        # Just doing nothing, only for example purpose
628        pass
629
630.. code-block:: python
631
632    # Omitting all backend declaration boilerplate code.
633
634    "OPTIONS": {
635        "CONNECTION_POOL_CLASS": "myproj.mypool.MyOwnPool",
636    }
637
638Customize connection factory
639^^^^^^^^^^^^^^^^^^^^^^^^^^^^
640
641If none of the previous methods satisfies you, you can get in the middle of the
642django-redis connection factory process and customize or completely rewrite it.
643
644By default, django-redis creates connections through the
645``django_redis.pool.ConnectionFactory`` class that is specified in the global
646Django setting ``DJANGO_REDIS_CONNECTION_FACTORY``.
647
648.. code-block:: python
649
650    class ConnectionFactory(object):
651        def get_connection_pool(self, params: dict):
652            # Given connection parameters in the `params` argument, return new
653            # connection pool. It should be overwritten if you want do
654            # something before/after creating the connection pool, or return
655            # your own connection pool.
656            pass
657
658        def get_connection(self, params: dict):
659            # Given connection parameters in the `params` argument, return a
660            # new connection. It should be overwritten if you want to do
661            # something before/after creating a new connection. The default
662            # implementation uses `get_connection_pool` to obtain a pool and
663            # create a new connection in the newly obtained pool.
664            pass
665
666        def get_or_create_connection_pool(self, params: dict):
667            # This is a high layer on top of `get_connection_pool` for
668            # implementing a cache of created connection pools. It should be
669            # overwritten if you want change the default behavior.
670            pass
671
672        def make_connection_params(self, url: str) -> dict:
673            # The responsibility of this method is to convert basic connection
674            # parameters and other settings to fully connection pool ready
675            # connection parameters.
676            pass
677
678        def connect(self, url: str):
679            # This is really a public API and entry point for this factory
680            # class. This encapsulates the main logic of creating the
681            # previously mentioned `params` using `make_connection_params` and
682            # creating a new connection using the `get_connection` method.
683            pass
684
685Use the sentinel connection factory
686^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
687
688In order to facilitate using `Redis Sentinels`_, django-redis comes with a
689built in sentinel connection factory, which creates sentinel connection pools.
690In order to enable this functionality you should add the following:
691
692
693.. code-block:: python
694
695    # Enable the alternate connection factory.
696    DJANGO_REDIS_CONNECTION_FACTORY = 'django_redis.pool.SentinelConnectionFactory'
697
698    # These sentinels are shared between all the examples, and are passed
699    # directly to redis Sentinel. These can also be defined inline.
700    SENTINELS = [
701        ('sentinel-1', 26379),
702        ('sentinel-2', 26379),
703        ('sentinel-3', 26379),
704    ]
705
706    CACHES = {
707        "default": {
708            "BACKEND": "django_redis.cache.RedisCache",
709            # The hostname in LOCATION is the primary (service / master) name
710            "LOCATION": "redis://service_name/db",
711            "OPTIONS": {
712                # While the default client will work, this will check you
713                # have configured things correctly, and also create a
714                # primary and replica pool for the service specified by
715                # LOCATION rather than requiring two URLs.
716                "CLIENT_CLASS": "django_redis.client.SentinelClient",
717
718                # Sentinels which are passed directly to redis Sentinel.
719                "SENTINELS": SENTINELS,
720
721                # kwargs for redis Sentinel (optional).
722                "SENTINEL_KWARGS": {},
723
724                # You can still override the connection pool (optional).
725                "CONNECTION_POOL_CLASS": "redis.sentinel.SentinelConnectionPool",
726            },
727        },
728
729        # A minimal example using the SentinelClient.
730        "minimal": {
731            "BACKEND": "django_redis.cache.RedisCache",
732
733            # The SentinelClient will use this location for both the primaries
734            # and replicas.
735            "LOCATION": "redis://minimal_service_name/db",
736
737            "OPTIONS": {
738                "CLIENT_CLASS": "django_redis.client.SentinelClient",
739                "SENTINELS": SENTINELS,
740            },
741        },
742
743        # A minimal example using the DefaultClient.
744        "other": {
745            "BACKEND": "django_redis.cache.RedisCache",
746            "LOCATION": [
747                # The DefaultClient is [primary, replicas...], but with the
748                # SentinelConnectionPool it only requires one "is_master=0".
749                "redis://other_service_name/db?is_master=1",
750                "redis://other_service_name/db?is_master=0",
751            ],
752            "OPTIONS": {"SENTINELS": SENTINELS},
753        },
754
755        # A minimal example only using only replicas in read only mode (and
756        # the DefaultClient).
757        "readonly": {
758            "BACKEND": "django_redis.cache.RedisCache",
759            "LOCATION": "redis://readonly_service_name/db?is_master=0",
760            "OPTIONS": {"SENTINELS": SENTINELS},
761        },
762    }
763
764.. _Redis Sentinels: https://redis.io/topics/sentinel
765
766Pluggable parsers
767~~~~~~~~~~~~~~~~~
768
769redis-py (the Python Redis client used by django-redis) comes with a pure
770Python Redis parser that works very well for most common task, but if you want
771some performance boost, you can use hiredis.
772
773hiredis is a Redis client written in C and it has its own parser that can be
774used with django-redis.
775
776.. code-block:: python
777
778    "OPTIONS": {
779        "PARSER_CLASS": "redis.connection.HiredisParser",
780    }
781
782Pluggable clients
783~~~~~~~~~~~~~~~~~
784
785django-redis is designed for to be very flexible and very configurable. For it,
786it exposes a pluggable backends that make easy extend the default behavior, and
787it comes with few ones out the box.
788
789Default client
790^^^^^^^^^^^^^^
791
792Almost all about the default client is explained, with one exception: the
793default client comes with replication support.
794
795To connect to a Redis replication setup, you should change the ``LOCATION`` to
796something like:
797
798.. code-block:: python
799
800    "LOCATION": [
801        "redis://127.0.0.1:6379/1",
802        "redis://127.0.0.1:6378/1",
803    ]
804
805The first connection string represents the primary server and the rest to
806replica servers.
807
808WARNING: Replication setup is not heavily tested in production environments.
809
810Shard client
811^^^^^^^^^^^^
812
813This pluggable client implements client-side sharding. It inherits almost all
814functionality from the default client. To use it, change your cache settings to
815something like this:
816
817.. code-block:: python
818
819    CACHES = {
820        "default": {
821            "BACKEND": "django_redis.cache.RedisCache",
822            "LOCATION": [
823                "redis://127.0.0.1:6379/1",
824                "redis://127.0.0.1:6379/2",
825            ],
826            "OPTIONS": {
827                "CLIENT_CLASS": "django_redis.client.ShardClient",
828            }
829        }
830    }
831
832WARNING: Shard client is still experimental, so be careful when using it in
833production environments.
834
835Herd client
836^^^^^^^^^^^
837
838This pluggable client helps dealing with the thundering herd problem. You can read more about it
839on link: `Wikipedia <http://en.wikipedia.org/wiki/Thundering_herd_problem>`_
840
841Like previous pluggable clients, it inherits all functionality from the default client, adding some
842additional methods for getting/setting keys.
843
844.. code-block:: python
845
846    CACHES = {
847        "default": {
848            "BACKEND": "django_redis.cache.RedisCache",
849            "LOCATION": "redis://127.0.0.1:6379/1",
850            "OPTIONS": {
851                "CLIENT_CLASS": "django_redis.client.HerdClient",
852            }
853        }
854    }
855
856This client exposes additional settings:
857
858- ``CACHE_HERD_TIMEOUT``: Set default herd timeout. (Default value: 60s)
859
860Pluggable serializer
861~~~~~~~~~~~~~~~~~~~~
862
863The pluggable clients serialize data before sending it to the server. By
864default, django-redis serializes the data using the Python ``pickle`` module.
865This is very flexible and can handle a large range of object types.
866
867To serialize using JSON instead, the serializer ``JSONSerializer`` is also
868available.
869
870.. code-block:: python
871
872    CACHES = {
873        "default": {
874            "BACKEND": "django_redis.cache.RedisCache",
875            "LOCATION": "redis://127.0.0.1:6379/1",
876            "OPTIONS": {
877                "CLIENT_CLASS": "django_redis.client.DefaultClient",
878                "SERIALIZER": "django_redis.serializers.json.JSONSerializer",
879            }
880        }
881    }
882
883There's also support for serialization using `MsgPack`_ (that requires the
884msgpack library):
885
886.. code-block:: python
887
888    CACHES = {
889        "default": {
890            "BACKEND": "django_redis.cache.RedisCache",
891            "LOCATION": "redis://127.0.0.1:6379/1",
892            "OPTIONS": {
893                "CLIENT_CLASS": "django_redis.client.DefaultClient",
894                "SERIALIZER": "django_redis.serializers.msgpack.MSGPackSerializer",
895            }
896        }
897    }
898
899.. _MsgPack: http://msgpack.org/
900
901Pluggable Redis client
902~~~~~~~~~~~~~~~~~~~~~~
903
904django-redis uses the Redis client ``redis.client.StrictClient`` by default. It
905is possible to use an alternative client.
906
907You can customize the client used by setting ``REDIS_CLIENT_CLASS`` in the
908``CACHES`` setting. Optionally, you can provide arguments to this class by
909setting ``REDIS_CLIENT_KWARGS``.
910
911.. code-block:: python
912
913    CACHES = {
914        "default": {
915            "OPTIONS": {
916                "REDIS_CLIENT_CLASS": "my.module.ClientClass",
917                "REDIS_CLIENT_KWARGS": {"some_setting": True},
918            }
919        }
920    }
921
922
923Closing Connections
924~~~~~~~~~~~~~~~~~~~
925
926The default django-redis behavior on close() is to keep the connections to Redis server.
927
928You can change this default behaviour for all caches by the ``DJANGO_REDIS_CLOSE_CONNECTION = True``
929in the django settings (globally) or (at cache level) by setting ``CLOSE_CONNECTION: True`` in the ``OPTIONS``
930for each configured cache.
931
932Setting True as a value will instruct the django-redis to close all the connections (since v. 4.12.2), irrespectively of its current usage.
933
934.. code-block:: python
935
936    CACHES = {
937        "default": {
938            "BACKEND": "django_redis.cache.RedisCache",
939            "LOCATION": "redis://127.0.0.1:6379/1",
940            "OPTIONS": {
941                "CLIENT_CLASS": "django_redis.client.DefaultClient",
942                "CLOSE_CONNECTION": True,
943            }
944        }
945    }
946
947SSL/TLS and Self-Signed certificates
948~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
949
950In case you encounter a Redis server offering a TLS connection using a
951self-signed certificate you may disable certification verification with the
952following:
953
954.. code-block:: python
955
956    CACHES = {
957        "default": {
958            "BACKEND": "django_redis.cache.RedisCache",
959            "LOCATION": "rediss://127.0.0.1:6379/1",
960            "OPTIONS": {
961                "CLIENT_CLASS": "django_redis.client.DefaultClient",
962                "CONNECTION_POOL_KWARGS": {"ssl_cert_reqs": None}
963            }
964        }
965    }
966
967
968License
969-------
970
971.. code-block:: text
972
973    Copyright (c) 2011-2015 Andrey Antukh <niwi@niwi.nz>
974    Copyright (c) 2011 Sean Bleier
975
976    All rights reserved.
977
978    Redistribution and use in source and binary forms, with or without
979    modification, are permitted provided that the following conditions
980    are met:
981    1. Redistributions of source code must retain the above copyright
982       notice, this list of conditions and the following disclaimer.
983    2. Redistributions in binary form must reproduce the above copyright
984       notice, this list of conditions and the following disclaimer in the
985       documentation and/or other materials provided with the distribution.
986    3. The name of the author may not be used to endorse or promote products
987       derived from this software without specific prior written permission.
988
989    THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS`` AND ANY EXPRESS OR
990    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
991    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
992    IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
993    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
994    NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
995    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
996    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
997    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
998    THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
999
1000
1001