Intro
-----
I found a question on SO for which Justin Lilly's answer was correct but not as thorough as I'd like, so I ended up working on a simple snippet that shows how to bind signals at runtime, which is nifty when you want to bind signals to an abstract class.
Bonus: simple cache invalidation!
Question
--------
[How do I use Django signals with an abstract model?](http://stackoverflow.com/questions/2692551/how-do-i-use-django-signals-with-an-abstract-model)
I have an abstract model that keeps an on-disk cache. When I delete the model, I need it to delete the cache. I want this to happen for every derived model as well.
If I connect the signal specifying the abstract model, this does not propagate to the derived models:
pre_delete.connect(clear_cache, sender=MyAbstractModel, weak=False)
If I try to connect the signal in an init, where I can get the derived class name, it works, but I'm afraid it will attempt to clear the cache as many times as I've initialized a derived model, not just once.
Where should I connect the signal?
Answer
------
I've created a custom manager that binds a post_save signal to every child of a class, be it abstract or not.
This is a one-off, poorly tested code, so beware! It works so far, though.
In this example, we allow an abstract model to define CachedModelManager as a manager, which then extends basic caching functionality to the model and its children. It allows you to define a list of volatile keys that should be deleted upon every save (hence the post_save signal) and adds a couple of helper functions to generate cache keys, as well as retrieving, setting and deleting keys.
This of course assumes you have a cache backend setup and working properly.
- managers
- models
- cache
- model
- manager
- signals
- abstract
- signal
- contribute_to_class