/
__init__.py
69 lines (55 loc) · 2.84 KB
/
__init__.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
from django.db import models
from django.db.models.query import QuerySet
from guacamole.lru import LRUCacheDict
class CachingQuerySet(QuerySet):
""" This class (designed to be overridden inside _caching_queryset_class) will look up objects in the cache (for some queries, basically just get's)
rather than hitting SQL for them.
"""
def __init__(self, *args, **kwargs):
super(CachingQuerySet, self).__init__(*args, **kwargs)
self.lookup_query_keywords = ['pk', 'pk__exact', '%s' % self.model._meta.pk.attname, '%s__exact' % self.model._meta.pk.attname]
self.lookup_query_keywords += self._get_manager().lookup_fields + [ field+"__exact" for field in self._get_manager().lookup_fields]
def _get_manager(self):
return self.model.objects
def _get_lookup_field(self, *args, **kwargs):
if (len(args) != 0) or (len(kwargs) != 1):
return None
for kw in self.lookup_query_keywords:
if kwargs.has_key(kw):
return kwargs[kw]
return None
def _cache_objects_in_result_cache(self):
super(CachingQuerySet, self).__len__() #This line might need to change with the implementation
if hasattr(self, "_result_cache") and self._result_cache and (not hasattr(self, "_saved_result_cache")):
for obj in self._result_cache:
for f in self._get_manager().lookup_fields + ['pk']:
self._get_manager().cache[getattr(obj, f)] = obj
self._saved_result_cache = True
def __len__(self):
self._cache_objects_in_result_cache()
return super(CachingQuerySet, self).__len__()
def get(self, *args, **kwargs):
lookup_field = self._get_lookup_field(*args, **kwargs)
if lookup_field: #In this case, we can probably find in the cache
try:
return self._get_manager().cache[lookup_field]
except KeyError:
result = super(CachingQuerySet, self).get(*args, **kwargs)
self._get_manager().cache[lookup_field] = result
return result
return super(CachingQuerySet, self).get(*args, **kwargs)
def _del_keys(dictionary, keys):
for k in keys:
if dictionary.has_key(k):
del dictionary[k]
class InMemoryCachingManager(models.Manager):
use_for_related_fields = True #Use this manager even for foreign keys
def __init__(self, *args, **kwargs):
self.lookup_fields = kwargs.get('lookup_fields', [])
self.cache = LRUCacheDict(max_size=kwargs.get("max_size", 1024), expiration=kwargs.get("expiration", 15*60))
_del_keys(kwargs, ['max_size', 'expiration', 'lookup_fields'] )
super(InMemoryCachingManager, self).__init__(*args, **kwargs)
def get_query_set(self):
return CachingQuerySet(self.model)
def clear_cache(self):
self.cache.clear()