-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi Zachary,

On 01/02/2012 10:55 PM, Zachary Voase 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'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?

Thanks for working on this. I think the decorator API you've selected is
a pretty good one for this; I agree with Russell that the methods belong
on a custom Manager, not on the model itself.

There will be some tricky points in the implementation. In particular,
QuerySets must remain pickleable (so they can be cached), which is
problematic if you are dynamically creating the QuerySet subclass. As
Donald Stufft points out on the ticket, we previously had an approach in
django-model-utils (manager_from) that was based on dynamically-created
QuerySet subclasses, and we moved away from it because it broke pickling
of QuerySets. There may be another way around this; I didn't look at the
problem in depth.

I have to say, this all feels to me a bit like polishing a turd; adding
ever-more complex hacks with metaclasses, dynamic subclasses, etc., all
to paper over what is really a more fundamental design problem. To wit:
a Manager is no different from a QuerySet in practice - it's just a sort
of "starter" queryset accessible from the model. If in practice people
pretty much always want to pair a custom Manager with a custom QuerySet
that has the same extra methods (and that is my experience), I think
it's telling us that those shouldn't be two separate classes at all.

I can't help but wonder if it would be possible to solve the problem
more thoroughly and remove the need for magic decorators by eliminating
the Manager class entirely and making it possible to simply assign a
QuerySet to a model, perhaps with a helper method:

   objects = manager(PersonQuerySet.filter(active=True))

I'm sure there are devils in the details here, too, but on cursory
inspection of the Manager code, it seems like it might be doable.

Carl
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk8DPlYACgkQ8W4rlRKtE2e+TQCffZZmaqKRc4Hyn3reUzYj6Cga
ja8AoNyIutFq4GuUfTgn5RgBMQaW/rJk
=AIQa
-----END PGP SIGNATURE-----

-- 
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