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