'Faking' related-object managers on instances?

4 views
Skip to first unread message

Jeff Forcier

unread,
Mar 15, 2007, 5:17:02 PM3/15/07
to Django users
Hi all,

I have an object hierarchy with varying levels of depth, and have a
few relationships that span multiple objects - in other words, if A is
related to B which is related to C, I will want to find all As related
to a given C object, even though they are *indirectly* related.

Since I use these relationships often and want to follow DRY, I have
made instance-level model methods, which are trivial, of course (not
asking *how* to do such a query!). However, since it's not currently
possible (?) to make custom instance-level Managers like the kind
found at the ends of "proper" relationships (i.e. c.b_set), my method
must simply return a QuerySet.

The problem is that QuerySets are not Managers, and so I will find
myself mucking with these objects in various spots and not knowing
offhand whether a given relationship attribute has e.g. the .all()
method, or not. If it's a regular Manager, and I want the entire set,
I must do myobj.relateditem_set.all(). If it's one of my custom
methods, that syntax will break as QuerySets do not have .all().

All I really want is the ability to have these extra faux-Manager
methods and for them to be indistinguishable in normal usage from the
real Managers. Any ideas? I'm unsure if it's wise to give QuerySets
a .all() method that simply returns 'self', although that would bring
the two object types closer together interface-wise.

Thanks,
Jeff

Malcolm Tredinnick

unread,
Mar 15, 2007, 5:43:06 PM3/15/07
to django...@googlegroups.com
On Thu, 2007-03-15 at 21:17 +0000, Jeff Forcier wrote:
[...]

> The problem is that QuerySets are not Managers, and so I will find
> myself mucking with these objects in various spots and not knowing
> offhand whether a given relationship attribute has e.g. the .all()
> method, or not. If it's a regular Manager, and I want the entire set,
> I must do myobj.relateditem_set.all(). If it's one of my custom
> methods, that syntax will break as QuerySets do not have .all().
>
> All I really want is the ability to have these extra faux-Manager
> methods and for them to be indistinguishable in normal usage from the
> real Managers. Any ideas? I'm unsure if it's wise to give QuerySets
> a .all() method that simply returns 'self', although that would bring
> the two object types closer together interface-wise.

It's not an insane idea. Certainly worth thinking about.

In the interim, you can work around this for your own purposes by
shoving an all() method into the QuerySet just before you return it from
each of your methods. Adds two lines of code each time, but doesn't
require touching the Django source. I'm thinking about something like:

queryset = .... # whatever magic is required
queryset.all = lambda self: return self
return queryset

Regards,
Malcolm

Jeff Forcier

unread,
Mar 15, 2007, 6:00:46 PM3/15/07
to Django users
I'm starting to think I should just email you directly with my
problems, Malcom :D Thanks a lot - I've done that sort of thing
before, but just wasn't thinking of it, it's definitely a fine stopgap
solution.

Since you seem to agree about adding the method to QuerySets in
general, I'll throw a quick ticket/patch into Trac so it's there -
would've done so initially but wasn't entirely sure if it was
appropriate.

Regards,
Jeff

On Mar 15, 5:43 pm, Malcolm Tredinnick <malc...@pointy-stick.com>
wrote:

Reply all
Reply to author
Forward
0 new messages