Caching query results in django

DjangoCaching

Django Problem Overview


I'm trying to find a way to cache the results of a query that won't change with frequency. For example, categories of products from an e-commerce (cellphones, TV, etc). I'm thinking of using the template fragment caching, but in this fragment, I will iterate over a list of these categories. This list is avaliable in any part of the site, so it's in my base.html file. Do I have always to send the list of categories when rendering the templates? Or is there a more dynamic way to do this, making the list always available in the template?

Django Solutions


Solution 1 - Django

Pop your cached query into Django's cache:

from django.core.cache import cache

cache.set('key', queryset)

Then create a context processor to add the value of the cache to all templates:

# myproject/myapp/context_processors.py

from django.core.cache import cache

def cached_queries():
    return {'cache', cache.get('key')}

Then add your context processor in your Django settings file:

TEMPLATE_CONTEXT_PROCESSORS += (
    'myproject.myapp.context_processors.cached_queries'
)

Now you will be able to access the cache variable in all generic templates and all templates which have a requests context, which a template is given if this is done in the view:

return render_to_response('my_template.html',
                          my_data_dictionary,
                          context_instance=RequestContext(request))

When to Set the Cache

It depends on what is contained in the cache. However a common problem is that Django only really gets to execute Python whenever a page request is sent, and this is often not where you want to do this kind of work.

An alternative is to create a custom management command for a particular app. You can then either run this manually when necessary, or more commonly set this to run as a cron job.

To create a management command you must create a class decended from Command inside of a management/commands directory located inside of an app:

# myproject/myapp/management/commands/update_cache.py

from django.core.management.base import NoArgsCommand
from django.core.cache import cache

class Command(NoArgsCommand):
    help = 'Refreshes my cache'

    def handle_noargs(self, **options):
        cache.set('key', queryset)

The name of this file is important as this will be the name of the command. In this case you can now call this on the command line:

python manage.py update_cache

Solution 2 - Django

You can also use johnny-cache for automatic caching of querysets. It will (by default) cache all querysets, but you can force it not to cache some.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMarcio CruzView Question on Stackoverflow
Solution 1 - DjangoMarcus WhybrowView Answer on Stackoverflow
Solution 2 - DjangoMatthew SchinckelView Answer on Stackoverflow