So-very-frequently I’ve wanted some form of full-model caching in Django. My use tends towards the simpler case. Basically, I have one or two ways I want to get at an instance quickly. For example, give me the user whos username is
yourmum. Or who’s email is
email@example.com. Or both.
The problem with that is, caching full model instances isn’t as simple as it seems it really should be. The first thought is, well, just pickle the whole thing and cache that based on what key I want to use (email, username, whatever it is). Unfortunately, that can fall on it’s face, given strange conditions model instances can end up in, and lead potentially lots of duplication in the cache (you’re paying for every byte in a cache).
Because of the complexity, there are a lot of libraries to do this for you. django-cache-machine, amongst many others.
However, the good developer you are, you fight out like a superhero against complexity and dependencies. DEPLEXITY (WO)MAN! I like it. You fight against complexity and dependencies in software projects, and bad breath.
I feel like Deplexity Man all the time, and I didn’t really want to add a whole series of dependencies to my project to accomplish a seemingly simple task – get at a
User object, and ideally from the cache.
So, I came up with this simple function, that returns a function, which gets things from your database, or the cache if they are already there.
Here are things it does:
* Complex queries, as long as it only returns one object. You can use whatever combination of
Q objects you desire. Behaves just like the
.get() method. * You can query for an object in multiple ways. There is a query cache in front of the actual full model cache. It’ll save the primary key of any query used. * Invalidation is handled for you. Whenever you set up a
ModelCache instance, it will remove instances from the database when they change or disappear. * Tell it not to raise
DoesNotExist if you’d rather just get back
None when the object isn’t there. Can lead to more idomatic code in some cases. You could even make a cool cached-db-backed-dictionary using it.