On 2/12/06, Robert Wittams <[EMAIL PROTECTED]> wrote:
I think I just got all turned around trying to follow the conversation - apologies for making you repeat yourself.
I don't have any particular problem with the name all() as currently implemented. However, if Article.objects is modified to return an uncached query set, I agree that the semantics are all wrong.
However, rather than having cached() as a factory/proxy method on the manager, wouldn't a better approach be to make cached() a 'cache enabling' clone method on QuerySet? i.e, cached() has the same operation as filter() - it returns a clone, but with caching enabled. Example usage:
- Article.objects is the only way to get a clean query set, caching disabled by default
- Article.objects.cached() takes the base query set, and returns a clone with caching enabled
- Article.objects.filter (...) returns a filtered, uncached query,
- Article.objects.filter(...).cached() is the same query, but with a cache.
- q = Article.objects.filter(...).cached(); q.cached() returns a second version of the filter query, with a clean cache
This also removes the need to proxy the QuerySet methods through the manager. This really appeals to me, because the Article.objects.filter() notation in the current implementation bugs me - to me, it should be
Article.objects.all().filter().
It might also be a good idea to add a 'reset_cache()' method to allow developers to reset the cache on a QuerySet (no-op if the query is not cached), and maybe even a 'non_cached()' method to return a cloned QuerySet with the cache disabled;
- Article.objects.cached().non_cached()
- Article.objects.non_cached()
being 2 examples of producing Article.objects in redundant ways.
You seem to have just repeated what I said .. I'm trying to work out
what point you are making.
I think I just got all turned around trying to follow the conversation - apologies for making you repeat yourself.
So basically the choices are:
a) .all(), I think it is fairly confusing in mapping the name to the
semantics
b) .cached(), the same semantics but at least it does what it says..
I don't have any particular problem with the name all() as currently implemented. However, if Article.objects is modified to return an uncached query set, I agree that the semantics are all wrong.
However, rather than having cached() as a factory/proxy method on the manager, wouldn't a better approach be to make cached() a 'cache enabling' clone method on QuerySet? i.e, cached() has the same operation as filter() - it returns a clone, but with caching enabled. Example usage:
- Article.objects is the only way to get a clean query set, caching disabled by default
- Article.objects.cached() takes the base query set, and returns a clone with caching enabled
- Article.objects.filter (...) returns a filtered, uncached query,
- Article.objects.filter(...).cached() is the same query, but with a cache.
- q = Article.objects.filter(...).cached(); q.cached() returns a second version of the filter query, with a clean cache
It might also be a good idea to add a 'reset_cache()' method to allow developers to reset the cache on a QuerySet (no-op if the query is not cached), and maybe even a 'non_cached()' method to return a cloned QuerySet with the cache disabled;
- Article.objects.cached().non_cached()
- Article.objects.non_cached()
being 2 examples of producing Article.objects in redundant ways.
c) externalise the caching, but this means decisions have to be made
about how to set the db_context etc etc. Logically this should be done
via events or middleware... and if transactions/unitofwork gets looked
at that would be the logical db_context I'm talking about above...
but I'm sure there will be cries of 'coupling' whatever decision is made
here... sigh.
Externalized caching is an interesting idea, but worries me slightly. Caching is one of those areas where the exact behaviour that you want can be highly application and situation dependent. I am more comfortable with putting making the developer take responsibility for what they want to cache, when they want to cache it, and the lifespan of that cache. Particularly if we can make the default behaviour 'don't cache', with caching being an opt-in behaviour (which the approach I described earlier on this mail would do).
A global cache that automagically works out the most recent version of a query has all sorts of potential for expectation to differ from implementation, (i.e., developer writes their app, doesn't get the result they expect because the caching implementation cleared a cached when they were not expecting it to be, and complains "why doesn't it work"). To boot, it will be a little hairy to implement, there will be cries of 'coupling', etc... it seems like asking for a lot of headaches without a whole lot of benefit at the end of the day.
Russ Magee %-)