4

I've had some trouble trying to reset my cache every hour for a particular django view.

Right now, I am using the cache_page decorator to cache my view using Memcached. But the cache expires after a while and the request is uncached from some users.

@cache_page(3600)
def my_view(request):
...

How do I write my own django manage.py command to refresh my cache for this view every hour from cron?

In other words, what do I put in my refresh_cache.py file mentioned in the answer here: Django caching - can it be done pre-emptively?

Thanks!

Community
  • 1
  • 1
Kiran
  • 461
  • 5
  • 15

2 Answers2

2

In your app, you can create a folder called management which contains another folder commands and an empty __init__.py file. Inside commands you create another __init__.py and a file where you write your custom command. Let's called it refresh.py:

# refresh.py

from django.core.management.base import BaseCommand, CommandError
from main.models import * # You may want to import your models in order to use  
                          # them in your cron job.

class Command(BaseCommand):
    help = 'Posts popular threads'

    def handle(self, *args, **options):
    # Code to refresh cache

Now you can add this file to your cron jobs. You can take a look at this tutorial but basically you use crontab -e to edit your cron jobs and crontab -l to see which cron jobs are running.

You can find all of this and more in the Django documentation.

r_31415
  • 8,752
  • 17
  • 74
  • 121
  • Thanks for the reply Robert. But could you please tell me what goes in the "#code to refresh cache". How do I call the view and set the response to cache using cache.set() – Kiran Oct 22 '12 at 20:13
  • You don't call the view. Instead, you add the part that does the refreshing. This is because the view may be doing something else that you don't want in a cron job. As for the specifics, see https://docs.djangoproject.com/en/dev/topics/cache/?from=olddocs#the-low-level-cache-api – r_31415 Oct 22 '12 at 20:16
  • what if i would like to cache my whole view (it's my homepage)? How would I set the cache to response of the whole view from the handle function in refresh.py? – Kiran Oct 22 '12 at 20:21
  • The documentation seems to suggest that cache_page doesn't cache the whole view, that is, every single process, but only its output. If that is true, you can get rid of this output calling .delete(). Add a prefix to your cached view and explore what keys are being used so you know exactly what to delete. As per a "delete cached view" command, I don't know if that exists. – r_31415 Oct 22 '12 at 20:29
  • Uhm... this can be helpful to you https://code.djangoproject.com/ticket/5815. Actually, there are several solutions: http://stackoverflow.com/questions/2268417/expire-a-view-cache-in-django – r_31415 Oct 22 '12 at 20:30
  • thanks Robert! This just became too complex (for me) to figure out right now. So I am going to manually cache the database lookup in my view rather than the whole view as u previously suggested – Kiran Oct 22 '12 at 21:02
1

I want to expand on Roberts answer to fill out the # Code to refresh cache

Timezome+location make caches much hard to work with, in my case I just disabled them, also I am not sure about using the test methods in the application code, but it seems to work nicely.

from django.core.management.base import BaseCommand, CommandError
from django.test.client import RequestFactory
from django.conf import settings

from ladder.models import Season
from ladder.views import season as season_view


class Command(BaseCommand):
    help = 'Refreshes cached pages'

    def handle(self, *args, **options):
        """
        Script that calls all season pages to refresh the cache on them if it has expired.

        Any time/date settings create postfixes on the caching key, for now the solution is to disable them.
        """

        if settings.USE_I18N:
            raise CommandError('USE_I18N in settings must be disabled.')

        if settings.USE_L10N:
            raise CommandError('USE_L10N in settings must be disabled.')

        if settings.USE_TZ:
            raise CommandError('USE_TZ in settings must be disabled.')

        self.factory = RequestFactory()
        seasons = Season.objects.all()
        for season in seasons:
            path = '/' + season.end_date.year.__str__() + '/round/' + season.season_round.__str__() + '/'
            # use the request factory to generate the correct url for the cache hash
            request = self.factory.get(path)

            season_view(request, season.end_date.year, season.season_round)
            self.stdout.write('Successfully refreshed: %s' % path)
jzahedieh
  • 1,570
  • 1
  • 15
  • 27