2014-09-03 159 views
1

我想弄清楚如何解決這個問題沒有任何運氣。情況是,作者有許多書籍按流派劃分,我希望當我查詢作者時,它會返回作者和按流派劃分的書對象。Django複雜queryset

Author object would have these properties: 
    name 
    fantasy - would have one book based by given date 
    crime - would have one book based by given date 
    romance - would have one book based by given date 

是否有一個健全的方式,通過不使成千上萬實現這一目標(如果我想有許多流派)的作者模型外鍵的?

class Author(models.Model): 
    name = models.CharField(u'Name',max_length=100) 

GENRE = (
    (0,u'Fantasy'), 
    (1,u'Crime'), 
    (2,u'Romance') 
) 

class Book(models.Model): 
    author = models.ForeignKey(Author) 
    name = models.CharField(u'Name',max_length=100) 
    genre = models.SmallIntegerField(u'Genre',choices=GENRE) 
    date = models.DateField(u'Publish date') 

編輯:

仔細檢查後sgarza62例子似乎工作不好用大量的數據。 所以我嘗試新的Django 1.7功能,預取

authors = Author.objects.all().prefetch_related(
     Prefetch("book", queryset=Book.objects.filter(genre=0,date_from__lte=datetime.datetime.now()), to_attr='x_fantasy'), 
     Prefetch("book", queryset=Book.objects.filter(genre=1,date_from__lte=datetime.datetime.now()), to_attr='x_crime'), 
     Prefetch("book", queryset=Book.objects.filter(genre=2,date_from__lte=datetime.datetime.now()), to_attr='x_romance') 
) 

但我有2個問題,這一點,怎麼只預取一個對象(最新的書在這個例子中)和第二,訂購基於預取的價值觀如何APPY。

回答

2

如果您查詢的是全部或多個作者,我推薦使用prefetching related fields。這會將所有相關對象一次性地抓到數據庫中,並將這些對象存儲在Queryset中。

authors = Author.objects.all().prefetch_related('book_set') 
for author in authors: 
    # accessing related field will not cause a hit to the db, 
    # because values are cached in Queryset 
    for book in author.books_set: 
     print book.genre 

如果您只查詢一位作者,那麼這不是什麼大不了的事。

author = Author.objects.get(pk=1) 
her_books = author.book_set 
for book in her_books: 
    print book.genre 

編輯我有一點很難理解你打算做什麼

。但是,如果你正在尋找各流派的最新著作,對於一個給定作者:

author = Author.objects.get(pk=1) 
author_books = author.book_set.order_by('-date') # most recent, first 
author_genres = set([b.genre for b in author_books]) 
for g in author_genres: 
    print next((b for b in author_books if b.genre==g), None) 

請記住,這些操作都是在查詢集,每一次都沒有命中數據庫。這很好,因爲查詢數據庫是一項昂貴的操作,而且大多數作者都有相對較小的作品列表,因此Querysets一般很小。

+0

是的,這是做到這一點的一種方式,但我想加入基於日期和作者的書以及稍後在db級別的自定義排序。 – user1156093 2014-09-03 19:50:01

+0

@ user1156093好吧,我想我明白你想要什麼。我編輯了我的答案;請看一下。 – sgarza62 2014-09-03 20:04:31

+0

謝謝,現在這就是我想要的。 – user1156093 2014-09-03 20:32:28