On 8/7/2010 3:03 PM, Daniel Roseman wrote: > On Aug 7, 7:47 pm, rmschne <rmsc...@gmail.com> wrote: >> I have a model like that I would like query down more than one level >> (using my nomenclature). >> >> class Library(models.Model) >> branch=models.CharField(max_length=100) >> >> class Book(models.Model) >> libraryid=models.ForeignKey(Library,related_name="books") >> >> class Chapter(models.Model) >> bookid=models.ForeignKey(Book,related_name="chapters") >> >> I can get a library object: >> >> l=Library.objects.filter(branch="Covent Garden") >> >> and then get a query set of all the books in Covent Garden >> >> b=l.books.all() >> >> How do I get a query set of all the chapters (in all the books) in the >> Covent Garden library? >> >> then then if I added >> >> class Paragraph(models.Model) >> chapterid=models.ForeignKey(Chapter,related_name="paragraphs") >> >> How would I get a query set of all the paragraphs (in all the chapters >> in all the books) in the Covent Garden library? > > Use the double-underscore syntax to traverse relationships. For all > chapters in books in Covent Garden: > > Chapter.objects.filter(bookid__libraryid__branch='Covent Garden') > > and all paragraphs in all chapters in all books in Covent Garden: > > > Paragraph.objects.filter(chapterid__bookid__libraryid__branch='Covent > Garden') > > and so on. > > Two things, though: firstly, your example query `b=l.books.all()` will > *not* work. `l` is a queryset, and doesn't have a `books` attribute. > If you're starting with an existing queryset, you can use `in`: > > b = Books.objects.get(libraryid__in=l) > > but in this case there's presumably only one Covent Garden branch, so > you should have just used `get` to get a single instance, rather than > a queryset, in the first place: > > l = Library.objects.get(branch='Covent Garden') > > and then your `l.books.all()` would have worked. > > Secondly, please drop those `id` suffixes. libraryid and bookid are > not ID fields, they are fields representing whole objects in other > models. Django automatically names the underlying database field > foo_id, so you will have libraryid_id and bookid_id behind the scenes.
It also makes your code read more smoothly without the "id" at the end of the foreign key field names. Then it would have been Paragraph.objects.filter(chapter__book__library__branch='Covent Garden') and so on. If you are dealing with an existing database whose column names cannot be changed you can use the db_column attribute, as in: chapter=models.ForeignKey(Chapter,related_name="paragraphs", db_column="chapterid") IMHO it's worth spending time thinking about naming to make your code more intuitive to the new reader. That new reader is often me, long after I ave forgotten the implementation details, and so the easier code is to understand and read the better. regards Steve -- I'm no expert. "ex" == "has-been"; "spurt" == "drip under pressure" "expert" == "has-been drip under pressure". -- You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-us...@googlegroups.com. To unsubscribe from this group, send email to django-users+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-users?hl=en.