1from django.core.exceptions import ImproperlyConfigured
2
3from . import Backend
4from .. import settings, utils, signals, config
5
6from pickle import loads, dumps
7
8
9class RedisBackend(Backend):
10
11    def __init__(self):
12        super().__init__()
13        self._prefix = settings.REDIS_PREFIX
14        connection_cls = settings.REDIS_CONNECTION_CLASS
15        if connection_cls is not None:
16            self._rd = utils.import_module_attr(connection_cls)()
17        else:
18            try:
19                import redis
20            except ImportError:
21                raise ImproperlyConfigured(
22                    "The Redis backend requires redis-py to be installed.")
23            if isinstance(settings.REDIS_CONNECTION, str):
24                self._rd = redis.from_url(settings.REDIS_CONNECTION)
25            else:
26                self._rd = redis.Redis(**settings.REDIS_CONNECTION)
27
28    def add_prefix(self, key):
29        return "%s%s" % (self._prefix, key)
30
31    def get(self, key):
32        value = self._rd.get(self.add_prefix(key))
33        if value:
34            return loads(value)
35        return None
36
37    def mget(self, keys):
38        if not keys:
39            return
40        prefixed_keys = [self.add_prefix(key) for key in keys]
41        for key, value in zip(keys, self._rd.mget(prefixed_keys)):
42            if value:
43                yield key, loads(value)
44
45    def set(self, key, value):
46        old_value = self.get(key)
47        self._rd.set(self.add_prefix(key), dumps(value, protocol=settings.REDIS_PICKLE_VERSION))
48        signals.config_updated.send(
49            sender=config, key=key, old_value=old_value, new_value=value
50        )
51