Add QuerySetManager and QuerySet to my Django snippets.
2 Random Django snippets I like to keep for quick reference
6 def cache_key_for_function(func, args=None, kwargs=None):
7 """Calculate a cache key for a function
9 Prefix keys with the module and function name
11 Use sha1 of repr() of args and kwargs as the final piece of the
12 cache key. This limits the maximum length (so we don't go over
13 memcached's limit, which I don't remember offhand) and swallows
16 This relies on accurate reprs - if the repr of the arguments are
17 the same, the hash will be the same, and the cached value will be
21 from hashlib import sha1
28 cache_key = "%s.%s(%s)" % (
29 func.__module__, func.__name__,
30 sha1(repr(args)+repr(kwargs)).hexdigest())
35 def cache_key_for_method(obj, method, args=None, kwargs=None):
36 "Like cache_key_for_function, but for methods"
37 from hashlib import sha1
39 cache_key = "%s.%s.%s(%s)" % (
40 obj.__class__.__module__,
41 obj.__class__.__name__,
43 sha1(repr(args)+repr(kwargs)).hexdigest())
48 def dictproperty(method):
49 """Turn dictionary or attribute access into a function call"""
51 class _Object(object):
52 def __init__(self, obj):
54 def __getattr__(self, attr):
55 return method(self.obj, attr)
56 __getitem__ = __getattr__
57 _Object.__name__ = method.__name__
59 return property(_Object)
62 def decorators(*decos):
63 """Some people say I need to handle my decorator problem.
67 The evaulation is such that the things on the left are on the
68 "outside" of the decorator chain. EG::
77 Which itself is, of course, a shortcut for::
83 # The reversed is needed - step through it, it'll make sense.
84 for deco in reversed(list(decos)):
90 def cached_function(func):
91 """A caching decorator for functions"""
92 from functools import wraps
93 from django.core.cache import cache
96 def _closure(*args, **kwargs):
97 cache_key = cache_key_for_function(
100 val = cache.get(cache_key)
102 val = func(*args, **kwargs)
103 cache.set(cache_key, val)
108 def cached_method(method):
109 """A caching decorator for methods"""
110 from functools import wraps
111 from django.core.cache import cache
114 def _closure(self, *args, **kwargs):
115 cache_key = cache_key_for_method(
116 self, method, (self,)+args, kwargs)
118 val = cache.get(cache_key)
120 val = method(self, *args, **kwargs)
121 cache.set(cache_key, val)
125 cached_property = decorators(property, cached_method)
128 def use_template(template_name, request_context=True):
129 """A view decorator that wraps render_to_response and uses RequestContext by default"""
130 from functools import wraps
131 from django.template import RequestContext
132 from django.shortcuts import render_to_response
134 def _decorator(func):
136 def _closure(request, *args, **kwargs):
137 # Use a different variable to avoid 'referenced before
138 # assignment'. 'template' is the kwarg used by
139 # direct_to_template; copy its interface for consistency.
140 actual_template = kwargs.pop("template", template_name)
141 actual_rc = kwargs.pop("request_context", request_context)
142 val = func(request, *args, **kwargs)
143 if isinstance(val, dict) and template_name is not None:
145 context = RequestContext(request)
146 return render_to_response(actual_template, val,
147 context_instance=context)
149 return render_to_response(actual_template, val)
155 # http://www.djangosnippets.org/snippets/562/#c673
156 class QuerySetManager(models.Manager):
157 # http://docs.djangoproject.com/en/dev/topics/db/managers/#using-managers-for-related-object-access
158 # Not working cause of:
159 # http://code.djangoproject.com/ticket/9643
160 use_for_related_fields = True
161 def __init__(self, qs_class=models.query.QuerySet):
162 self.queryset_class = qs_class
163 super(QuerySetManager, self).__init__()
165 def get_query_set(self):
166 return self.queryset_class(self.model)
168 def __getattr__(self, attr, *args):
170 return getattr(self.__class__, attr, *args)
171 except AttributeError:
172 return getattr(self.get_query_set(), attr, *args)
175 class QuerySet(models.query.QuerySet):
176 """Base QuerySet class for adding custom methods that are made
177 available on both the manager and subsequent cloned QuerySets"""
180 def as_manager(cls, ManagerClass=QuerySetManager):
181 return ManagerClass(cls)
184 return self.order_by("?")