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.

Reply via email to