Patterns for dealing with memcache Caching in Django
I have a big Django project with several interrelated projects and a lot of caching in use. It currently has a file which stores cache helper functions. So for example, get_object_x(id) would check cache for this object and if it wasn't there, go to the DB and pull it from there and return it, cachin开发者_Go百科g it along the way. This same pattern is followed for caching groups of objects and the file is also used for for invalidation methods.
A problem has arisen in the imports between apps though. The app models file has a number of helper functions which we want to use cache for, and the cache_helpers file obviously needs to import the models file.
So my question is: What is a better way of doing this that doesn't expose the code to circular import issues (or maybe just a smarter way in general)? Ideally we could do invalidation in a better, less manual way as well. My guess is that the use of Django Custom Managers and Signals is the best place to start, getting rid of the cache_helpers file altogether, but does anyone have any better suggestions or direction on where to look?
A general Python pattern for avoiding circular imports is to put one set of the imports inside the dependent functions:
# module_a.py
import module_b
def foo():
return "bar"
def bar():
return module_b.baz()
# module_b.py
def baz():
import module_a
return module_a.foo()
As for caching, it sounds like you need a function that looks a bit like this:
def get_cached(model, **kwargs):
timeout = kwargs.pop('timeout', 60 * 60)
key = '%s:%s' % (model, kwargs)
result = cache.get(key)
if result is None:
result = model.objects.get(**kwargs)
cache.set(key, result, timeout)
return result
Now you don't need to create "getbyid" methods for every one of your models. You can do this instead:
blog_entry = get_cached(BlogEntry, pk = 4)
You could write similar functions for dealing with full QuerySets instead of just single model objects using .get() method.
Since you indicated you're caching Django ORM model instances, take a look at django-orm-cache, which provides automated caching of model instances and is smart about when to invalidate the cache.
Your circular imports won't be an issue - all you need to do is extend the models you need to cache from the ormcache.models.CachedModel
class instead of Django's django.db.models.Model
, and you get caching "for free."
精彩评论