This is all crazy. You people are crazy. I figured this out months ago: http://code.djangoproject.com/ticket/980, we didn't have the concept of the manager back then, of course, but the basic principles are there, (query == filter).
If you cache the count, len() and bool() can be called over and over for all you care. Model.objects can't be a query, it's the manager. Sure it sounds like all the objects, but that's what you have all() for. Although it appears elegant at first, I think it will cause more problems that it is worth. The query object needs to query (or return a cache) on: __iter__, __len__, __getitem__, __contains__, __bool__, and __str__ (__repr__ optionally, although I thought it would be more usefull to return the created SQL, though) It should cache the results always, but then define a "fetch()" function, which immediately resends and returns the query, and probably a "clear_cache()" function as RJ suggested. _set, I waiver on. It's certainly scientifically correct. I remember though when RJ first suggested it, my immediate reaction was not the noun 'set', but the verb 'to set', so I think it could cause some confusion for new users. In the end I am unsure. What I am sure about is that each Manager should have a get_related_manager(field). This would be a factory function, that assigns object_set, so you could redo it to do objects, if you wanted. Reporter.objects.order_by('-lname', 'fname') is incorrect as far as I can see. The manager cannot hold this state info. This is more correct: q = Reporter.objects.filter(fname='John') q.order_by('-lname', 'fname') or: print Reporter.objects.filter(fname='John').order_by('-lname', 'fname') Thanks