H'ok, got this working. First off, I had a brain hiccup: my model was
one-to-many (the actual model is more complicated than my Book
example; I just used the Book to illustrate my point).

What I ended up doing was basically what you suggested to do using
Django's ORM: I ran two queries, one for Books and one for Authors.
Then I looped through and sewed them all together.

That was a fairly simple solution (which is the best kind), and I
thank you for pointing it out to me!

On Sep 1, 7:40 pm, Eric Abrahamsen <[EMAIL PROTECTED]> wrote:
> On Sep 2, 2008, at 9:52 AM,MrJogowrote:
>
>
>
> > I read that post, and now have a general idea of what to do, but I'm
> > still confused on the specifics. It doesn't help that my SQL is VERY
> > rusty.
>
> I'm really not the one to be walking you through this, since my own  
> success was a bit of a fluke, but maybe I can nudge things in the  
> right direction.
>
>
>
> > Am I supposed to use cursor.execute() to do the INITIAL lookup? That
> > is, instead of calling a filter, or whatnot, on each book entry, I do
> > a cursor.execute that gets the books I want AND the related living
> > authors in one fell swoop? Do I set that up as a custom Manager?
>
> The way I did it was one query for the base queryset, and then one  
> cursor.execute() that pulled out the extra info I wanted to attach to  
> each queryset object. You certainly could do one cursor.execute() to  
> retrieve the entire query, but then you'd have to work with raw data,  
> not nice python objects.
>
> Come to think of it, you might not even want to use cursor.execute().  
> I did that because all I wanted was an extra list of pks, not full  
> model instances. If you want to use the living authors as full  
> instances (ie call methods on them), then you could do this all with  
> Django's ORM: one query of books with living authors, one query of  
> living authors, then python to attach the two.
>
> Whether you set it up as custom manager or not mostly depends on how  
> often you expect to be using this particular query. More than once or  
> twice, and you might as well make it a manager method.
>
> > What would be the SQL for that? My model does not create an in between
> > table (such as appname_book_authors).
> > How do I append my results to a queryset?
>
> It depends on your table set up, but the basic concept is looping over  
> books, and giving each book a new attribute 'living_authors' which is  
> a list of Author instances.
>
> The model definitions you posted earlier are a little odd, you say  
> you've got a M2M relationship between books and author, but actually  
> your Author has a foreign key to Book – ie, each Author can only have  
> written one book. If it were a M2M relationship, you'd probably put an  
> M2M 'authors' field on Book, and leave Author alone. That would create  
> the appname_book_authors table...
>
> Let me know if the model structure you posted is really the one you  
> want to use, and I might be able to help with the next step...
>
> Yours,
> Eric
>
> > I tried to figure these things out on my own, but I just couldn't wrap
> > my head around it.
>
> > On Aug 26, 2:32 am, Eric Abrahamsen <[EMAIL PROTECTED]> wrote:
> >> On Aug 26, 2008, at 5:00 PM,MrJogowrote:
>
> >>> I guess I saw it as operating on a group of objects: filtering the
> >>> group of authors related to my_book by is_living. I also think I got
> >>> RelatedManager confused with Manager.
>
> >> Yaar, it can be a bit confusing. I guess what's important is to
> >> remember which model you've started your query with – all queries are
> >> relative to that table. I wonder if it's possibly to subclass
> >> RelatedManager and add custom methods, come to think of it...
>
> >>> I think I can handle two db hits, although it's not optimal. I wish
> >>> there was a way to get a set of data filtered on many levels (ie,  
> >>> only
> >>> books with living authors AND only the related living authors) with
> >>> one command/db hit.
>
> >> It will be more than two db hits if you've got to call
> >> living_authors() on every book in the set!
>
> >> Actually I needed to do something like this recently, here's a link  
> >> to
> >> the relevant 
> >> thread:http://groups.google.com/group/django-users/browse_thread/thread/9be1
> >> ...
>
> >> There's a lot of cruft in that thread, the basic idea is using
> >> cursor.execute() to do your subqueries (selecting all living authors
> >> per book), and then using pure python to attach those subqueries to
> >> your larger book queryset. It's not as painful as it sounds.
>
> >> Lastly, there are rumors of aggregation support coming soon/already
> >> here, but I'm not sure how that works (or even if it will solve these
> >> kinds of problems) so will say no more...
>
> >> E
>
> >>> On Aug 26, 2:10 am, Eric Abrahamsen <[EMAIL PROTECTED]> wrote:
> >>>> On Aug 25, 2008, at 3:11 PM,MrJogowrote:
>
> >>>>> How do I create a custom manager for many-to-many traversal? An
> >>>>> example will illustrate what I want to do better. Suppose I have  
> >>>>> the
> >>>>> following models.py:
>
> >>>>> class Book(models.Model):
> >>>>>  title = models.CharField(max_length=100)
>
> >>>>> class Author(models.Model):
> >>>>>  books = models.ForeignKey(Book)
> >>>>>  name = models.CharField(max_length=100)
> >>>>>  is_alive = models.BooleanField()
>
> >>>>> This is a many-to-many relationship: a book can have multiple
> >>>>> authors
> >>>>> and an author can have written multiple books.
>
> >>>>> If I have a book object my_book, and I want to get all the
> >>>>> authors, I
> >>>>> do my_book.author_set.all(). How can I set up a custom manager to
> >>>>> only
> >>>>> get living authors of that book, so I could do something like
> >>>>> my_book.livingauthor_set.all()?
>
> >>>> Custom managers are usually used for table-level functionality, ie
> >>>> you'd make a manager method that filters or acts on a *group* of
> >>>> books, not one single book. The usual thing to do when you want
> >>>> something from a single object is to put a custom method on Book,
> >>>> which returns living authors, like:
>
> >>>> def living_authors(self):
> >>>>      return self.author_set.filter(is_alive=True)
>
> >>>> What I don't know is if there's any way to keep this from making
> >>>> another db hit every time you call some_book.living_authors().
> >>>> QuerySets can't be further filtered once they've been evaluated, so
> >>>> using select_related() on the original Book QuerySet might not
> >>>> help...
>
> >>>> Yours,
> >>>> Eric
>
> >>>>> Thanks
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-users@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to