On Tue, Jan 3, 2012 at 11:43 AM, Carl Meyer <[email protected]> wrote:

> -----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.
>
>
I haven't analyzed your suggestion in detail Carl, but there is a good
reason for managers to exist:

querysets cache internally on iteration, managers are not directly
evaluable, but were they you could end up doing something like:

for instance in Model.objects:
    pass

and you'd cache those results in global state.

Alex

-- 
"I disapprove of what you say, but I will defend to the death your right to
say it." -- Evelyn Beatrice Hall (summarizing Voltaire)
"The people's good is the highest law." -- Cicero

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