On Tue, Jan 3, 2012 at 1:55 PM, Zachary Voase <[email protected]> wrote:
> At the moment it's very easy to add methods to individual models, just
> by putting a method on the model class itself which accepts 'self'.
> However, defining business logic on collections of records is
> currently pretty complicated — you have to create at least a custom
> Manager subclass, and if you want to chain those methods together
> you'll need a QuerySet subclass. An example of the desired behaviour,
> and the steps required for it, is shown in [1].
>
> I originally created django-qmixin [2] to tackle this problem; you can
> define methods which will be present on the manager and all querysets
> produced therefrom, including on relations. However, the django-qmixin
> approach of creating a mixin and then including that on the Manager
> class object doesn't really gel with the rest of Django core. I've
> worked out two approaches which are easier for novices to understand,
> and match the idioms of the rest of Django. They both involve adding a
> @models.querymethod decorator, which would be applied to methods which
> operate on collections of records (i.e. querysets). It's an analog to
> Python's @classmethod.
>
> The first approach [3] involves adding these querymethods to the model
> class itself; the second [4] adds them to a manager subclass (but
> without the trouble of the QuerySet subclass). I prefer the former,
> for simplicity, but you may believe otherwise.

I think I'm in the "otherwise" camp -- primarily for reasons of namespacing.

The QuerySet and the Manager are different classes, but they effective
share a namespace. It's good practice (and a practice that your
example demonstrates) for the Manager and the QuerySet to use the same
names for their methods; it makes a certain amount of sense to me that
there should be handy shortcut to automagically perform this
duplication.

However, the same isn't true of the Model and the QuerySet. The API
for a Model and the API for a QuerySet are quite different -- and
intentionally so. Sticking QuerySet methods on a Model in order to
avoid a couple of lines of manager definition and registration seems a
little odd to me, in an "explicit is better that implicit" kinda way.
For my money, it's better to be explicit that you're defining a custom
manager.

In practical terms, there are two ways that this could manifest.

Firstly, if there is a namespace collision -- i.e., if you want
MyObject.objects.foo() and myinstance.foo() do different things. I
can't think of an obvious practical example off the top of my head,
but anything where the verb and collective noun aren't distinguishable
would be a candidate for a collision.

Secondly, if you have more than one manager, you may want a method on
one manager, but not the other. For this case, we'd need to have the
Manager-based shortcut anyway, or tell people that if you have
multiple managers, you need to do the full-manual queryset definion.

> I'm working on a proof-of-concept implementation, but I feel it's more
> important to agree on the interface and rationale beforehand. Any
> thoughts?

As I mentioned to you in person at DC.eu -- details notwithstanding,
I'm +1 to this idea. QuerySet+Manager is a common pattern, and it
deserves to have a simplification in Django's core.

Yours,
Russ Magee %-)

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.

Reply via email to