Last active
August 29, 2015 14:26
-
-
Save agrn/0dfd76153ba36f41cfef to your computer and use it in GitHub Desktop.
Redis cache backend for Django
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Copyright (c) 2015, Alban Gruin <[email protected]> | |
# | |
# Permission to use, copy, modify, and/or distribute this software for any | |
# purpose with or without fee is hereby granted, provided that the above | |
# copyright notice and this permission notice appear in all copies. | |
# | |
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
"Redis cache backend" | |
from django.core.cache.backends.base import DEFAULT_TIMEOUT, BaseCache | |
import redis | |
class RedisCache(BaseCache): | |
def __init__(self, server, params): | |
super(RedisCache, self).__init__(params) | |
self._server = params.get('LOCATION', 'localhost') | |
self._port = params.get('PORT', 6379) | |
self._db = params.get('DB', 0) | |
self._password = params.get('PASSWORD', None) | |
self._unixSocket = self._server.startswith('unix:/') | |
if self._unixSocket: | |
self._server = self._server[5:] | |
def __contains__(self, key): | |
return self.has_key(key) | |
@property | |
def _cache(self): | |
if not hasattr(self, '_client'): | |
if self._unixSocket: | |
self._client = redis.StrictRedis(unix_socket_path=self._server, | |
db=self._db, | |
password=self._password) | |
else: | |
self._client = redis.StrictRedis(host=self._server, | |
port=self._port, db=self._db, | |
password=self._password) | |
return self._client | |
def add(self, key, value, timeout=DEFAULT_TIMEOUT, *args, **kwargs): | |
if hasattr(value, '__len__') and len(value) <= 0: | |
return True | |
pipe = self._cache.pipeline() | |
if isinstance(value, list): | |
pipe.rpush(key, *value) | |
elif isinstance(value, dict): | |
pipe.hmset(key, value) | |
else: | |
pipe.set(key, value) | |
pipe.expire(key, timeout) | |
if pipe.execute() == [True, True]: | |
return True | |
else: | |
return False | |
def clear(self): | |
self._cache.flushdb() | |
def close(self): | |
if getattr(self, '_client', None) is not None: | |
del self._client | |
def decr(self, key, delta=1, *args, **kwargs): | |
return self._cache.decrby(key, -delta) | |
def delete(self, key, *args, **kwargs): | |
self._cache.delete(key) | |
def delete_many(self, keys, *args, **kwargs): | |
for key in keys: | |
self.delete(key, *args, **kwargs) | |
def get(self, key, default=None): | |
if self._cache.exists(key): | |
if self._cache.type(key) == 'string': | |
return self._cache.get(key) | |
elif self._cache.type(key) == 'list': | |
return self._cache.lrange(key, 0, -1) | |
elif self._cache.type(key) == 'hash': | |
return self._cache.hgetall(key) | |
else: | |
return default | |
def get_many(self, keys, *args, **kwargs): | |
return dict(zip(keys, [self.get(key) for key in keys])) | |
def get_or_set(self, key, default=None, timeout=DEFAULT_TIMEOUT, *args, | |
**kwargs): | |
if default is None: | |
raise ValueError('You need to specify a value.') | |
if self.has_key(key): | |
return self.get(key) | |
else: | |
if callable(default): | |
default = default() | |
if self.add(key, default, timeout, *args, **kwargs): | |
return self.get(key, *args, **kwargs) | |
return False | |
def has_key(self, key, *args, **kwargs): | |
return self._cache.exists(key) | |
def incr(self, key, delta=1, *args, **kwargs): | |
return self._cache.incrby(key, delta) | |
def set(self, key, value, timeout=DEFAULT_TIMEOUT, *args, **kwargs): | |
return self.add(key, value, timeout) | |
def set_many(self, data, timeout=DEFAULT_TIMEOUT, *args, **kwargs): | |
for key, value in data.items(): | |
self.set(key, value, timeout, *args, **kwargs) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment