Expire a View-Cache in Django

Expire a view-cache in Django?

This solution works for django versions before 1.7

Here's a solution I wrote to do just what you're talking about on some of my own projects:

def expire_view_cache(view_name, args=[], namespace=None, key_prefix=None):
"""
This function allows you to invalidate any view-level cache.
view_name: view function you wish to invalidate or it's named url pattern
args: any arguments passed to the view function
namepace: optioal, if an application namespace is needed
key prefix: for the @cache_page decorator for the function (if any)
"""
from django.core.urlresolvers import reverse
from django.http import HttpRequest
from django.utils.cache import get_cache_key
from django.core.cache import cache
# create a fake request object
request = HttpRequest()
# Loookup the request path:
if namespace:
view_name = namespace + ":" + view_name
request.path = reverse(view_name, args=args)
# get cache key, expire if the cached item exists:
key = get_cache_key(request, key_prefix=key_prefix)
if key:
if cache.get(key):
# Delete the cache entry.
#
# Note that there is a possible race condition here, as another
# process / thread may have refreshed the cache between
# the call to cache.get() above, and the cache.set(key, None)
# below. This may lead to unexpected performance problems under
# severe load.
cache.set(key, None, 0)
return True
return False

Django keys these caches of the view request, so what this does is creates a fake request object for the cached view, uses that to fetch the cache key, then expires it.

To use it in the way you're talking about, try something like:

from django.db.models.signals import post_save
from blog.models import Entry

def invalidate_blog_index(sender, **kwargs):
expire_view_cache("blog")

post_save.connect(invalidate_portfolio_index, sender=Entry)

So basically, when ever a blog Entry object is saved, invalidate_blog_index is called and the cached view is expired. NB: haven't tested this extensively, but it's worked fine for me so far.

Can I get expiration time of specified key in django cache?

cache._expire_info.get('foo') 

to get the unix timestamp

Automatically cache view after cache expires in django

Nothing out of the box afaik. Your best bet would be probably running a background task (django manage command from crontab, or celery) every 5 min and manually caching that value under some key (with the expiration set to never expire), then reading it in the view by the key (no more whole page caching). I think this is the only way to keep 100% of requests cached and not return any stale data (older than 5 min).

If you don't mind showing the stale data to the first user after the 5 min have passed, then you can store a timestamp along with the value inside the cache to mark when this cache was last refreshed. This timestamp then can be used to manually check if 5 min have passed since the last refresh (this is to battle memcached standard behavior of returning nothing for expired values). If 5 min have passed, return the stale cached value to a user immediately and spawn a background thread to update the cached value.

Django per-view caching: set expiry time rather than cache timeout?

I don't know if there is a nice built in way to do it, but if not you could create your own decorator that would essential do the same thing as cache_page

But you could give your decorator a time string and inside of it, you could calculate the number of seconds until that time, then just call the original cache function, with the seconds until the time you specified

Is there a way to set an expiration time for a Django cache lock?

I've answered my own question. The following arguments are available for cache.lock():

    def lock(
self,
key,
version=None,
timeout=None,
sleep=0.1,
blocking_timeout=None,
client=None,
thread_local=True,
):

Cross referencing that with comments from the Python Redis source, which uses the same arguments:

   ``timeout`` indicates a maximum life for the lock.
By default, it will remain locked until release() is called.
``timeout`` can be specified as a float or integer, both representing
the number of seconds to wait.
``sleep`` indicates the amount of time to sleep per loop iteration
when the lock is in blocking mode and another client is currently
holding the lock.
``blocking`` indicates whether calling ``acquire`` should block until
the lock has been acquired or to fail immediately, causing ``acquire``
to return False and the lock not being acquired. Defaults to True.
Note this value can be overridden by passing a ``blocking``
argument to ``acquire``.
``blocking_timeout`` indicates the maximum amount of time in seconds to
spend trying to acquire the lock. A value of ``None`` indicates
continue trying forever. ``blocking_timeout`` can be specified as a
float or integer, both representing the number of seconds to wait.

Therefore, to set the maximum time period of 2 seconds for which a cache lock takes effect, do something like this:

with cache.lock(key='my_cache_lock_key', timeout=2):
# Execute some logic here, such as:
cache.set('some_key', 'Hello world', 3000)


Related Topics



Leave a reply



Submit