2014-09-03 119 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