Re: Custom manager for many-to-many traversal

2008-09-03 Thread MrJogo

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

Re: Custom manager for many-to-many traversal

2008-09-01 Thread Eric Abrahamsen


On Sep 2, 2008, at 9:52 AM, MrJogo wrote:

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

Re: Custom manager for many-to-many traversal

2008-09-01 Thread MrJogo

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.

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?

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?

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



Re: Custom manager for many-to-many traversal

2008-08-26 Thread Eric Abrahamsen


On Aug 26, 2008, at 5:00 PM, MrJogo wrote:

>
> 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/9be16ce8fc13643b/3fdadd9f82dcdf57

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



Re: Custom manager for many-to-many traversal

2008-08-26 Thread MrJogo

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.

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.

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



Re: Custom manager for many-to-many traversal

2008-08-25 Thread Eric Abrahamsen


On Aug 25, 2008, at 3:11 PM, MrJogo wrote:

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



Re: Custom manager for many-to-many traversal

2008-08-25 Thread MrJogo

I could, but I need to do it in a template, and from what I
understand, passing variables to method calls in the template language
is a pain, or at least ugly. I think a custom manager is the elegant,
"proper" way to so it (someone can correct me if I'm wrong.

On Aug 25, 10:31 am, John M <[EMAIL PROTECTED]> wrote:
> Since my_book.auther_set.all() returns a QS, can't you just say
> something like ...all().filter(author__isalive=True) or something like
> that?  I've never tried, but I thought that django would figure it
> out?
>
> J
>
> On Aug 25, 12:11 am,MrJogo<[EMAIL PROTECTED]> wrote:
>
> > 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()?
>
> > 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
-~--~~~~--~~--~--~---



Re: Custom manager for many-to-many traversal

2008-08-25 Thread John M

Since my_book.auther_set.all() returns a QS, can't you just say
something like ...all().filter(author__isalive=True) or something like
that?  I've never tried, but I thought that django would figure it
out?

J

On Aug 25, 12:11 am, MrJogo <[EMAIL PROTECTED]> wrote:
> 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()?
>
> 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
-~--~~~~--~~--~--~---



Custom manager for many-to-many traversal

2008-08-25 Thread MrJogo

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()?

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