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.
