Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to cache query result in django?

I am trying to cache query results on my django app. However, it seems that it is caching the whole app. I tried following logi:

def cacheView():
  result = cache.get('key')
  if result is None:
    result = Model.objects.get(id=1)
    cache.set('key', 'result')

I am calling this method when user logs in. However, if I try to logout after login, it keeps me on same page as if I am still logged in. I tried to follow the Django documentation on cache at http://docs.djangoproject.com/en/1.2/topics/cache/ but to no success.

Another thing I tried is that if I try to use the cache decorator just above the view as:

@cache_control(max_age=1000)
def cacheView():
 ...

it does it gives an error saying "response header not defined". I am new to django and sure that I missed something. Any idea?

like image 441
jindals Avatar asked Sep 27 '10 14:09

jindals


2 Answers

RTFM :) Official Django Docs: Caching and QuerySets

Each QuerySet contains a cache, to minimize database access. (...)

and:

In a newly created QuerySet, the cache is empty. The first time a QuerySet is evaluated -- and, hence, a database query happens -- Django saves the query results in the QuerySet's cache and returns the results that have been explicitly requested (e.g., the next element, if the QuerySet is being iterated over). Subsequent evaluations of the QuerySet reuse the cached results.

Caching is done automagically in case of QuerySets (results of Queries).

EDIT: As for your code pasted in the question. If the key doesn't already exist in cache you have to create it with add() method but remember that it will expire by default after 30sec. If you want it to be kept longer you have to add timeout option to add()/set() method.

If you want to cache for whole your site (to ie. decorators as you used them), you need to add proper middleware to your MIDDLEWARE_CLASSES in settings.py (in this exact order, because middleware order matters, it is loaded one by one as you define them):

MIDDLEWARE_CLASSES = (
    # ...
    'django.middleware.cache.UpdateCacheMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.cache.FetchFromCacheMiddleware',
    # ...
)

If you don't have them, then you'll be receiving bad header errors every time you'll use caching-per-site capabilities.

like image 98
bx2 Avatar answered Oct 13 '22 00:10

bx2


From your example it's not clear why the logout would fail, but it shouldn't be anything to do with caching a model (unless you're caching the User model and using the cached user for authentication instead of request.user?)

It's fine to use cache.get and cache.set the way you are (set will create a new key if it doesn't exist).

Caching queries can be difficult as you need to take care of invalidating the cache when data changes so as not to serve stale results.

Have a look at these query-caching libraries for Django which aim to make things easier:

http://jbalogh.me/2010/02/09/cache-machine/

http://packages.python.org/johnny-cache/queryset_cache.html

like image 21
Anentropic Avatar answered Oct 12 '22 23:10

Anentropic