> Taking this approach a little further, it could also address Adrian's > Manager __call__ problem with Jacob's Article.objects() proposal. > Rather than exposing the manager itself, expose an interface that can > be used as a factory for producing Query objects. Keep the Manager > internally as a mechanism for managing database connections and SQL > composition, but don't expose it as the Article.objects member. > > On the class itself, Article.objects(), Article.values(), > Article.in_bulk() become factory methods for producing Query objects > which, when iterated, provide objects of the expected type (instances, > dictionaries, etc). > > filter, order_by, etc are kept as methods on a query object itself, > rather than methods on the manager. If you want to apply a filter, use > Article.objects().filter(headline="foo"). The metaphor here is 'make a > basic query object, then narrow it with a filter'. > > On class instances, article_obj.sites() becomes the analogous factory > method for queries.
I've got to say, this is absolutely horrible and non-obvious. API design should not be an exercise in how clever or confusing you should be - it should be non-surprising. Article.objects acting as a set of Articles is non-surprising. Article.objects.filter(whatever="fish") returning a new filtered set is non surprising. > This approach also simplifies one use case for multiple managers - > pre-filtered Managers. If you need every query to have a particular > filter pre-applied, add a class method that returns > objects().filter(...) as required. And this is simpler than class Something: name = CharField(maxlength=100) objects = Manager() bad_objects = objects.filter(name_startswith="bad") how? (Yes, its a contrived example.)