2015-04-02 42 views
0

我有两个在与ManyToManyField关系Django模型Django的ManyToManyField访问相关数据

Book模型

class Book(models.Model): 
    title = models.TextField() 
    authors = models.ManyToManyField('authors.Author') 

作者型号

class Author(models.Model): 
    name = models.CharField(max_length=200) 

比方说,我的最佳方式通过运行查询

01获取所有书籍
books = Book.objects.filter(name="some value").prefect_related('authors') 

什么是优化的方式来让所有的作者与上述结果书有关。

什么,我想现在是

authors = [] 
for book in books: 
    for author in book.authors.all(): 
     authors.append(author.id) 
authors = Author.objects.filter(id__in=authors).distinct() 

但是这个看上去很昂贵。什么是获得相关作者设置的最佳途径。

回答

2

即使使用昂贵的方法,也不需要在最后再次查询作者:在每个内部循环中,author已经是一个Author实例,因此您可以将其添加到列表中而不是ID。

但是你说得对,有一个更便宜的方法来做到这一点,那就是直接在查询中使用关系。与往常一样,如果你想作者,你应该开始作者和遍历书籍:

authors = Author.objects.filter(book__in=Book.authors.all()) 

这将转化为一个子查询单个查询。因为这是一个简单的JOIN

authors = Author.objects.exclude(book=None) 

,它应该让你在这种情况下,相同的结果:

这可能是更便宜。

+0

是不是book_set,而不是你使用它作为一个字段 – 2015-04-02 13:36:33

+0

没有的方式,查找你总是使用字段的小写名称,无论它是向前还是向后。 – 2015-04-02 13:39:53

1

如果你只需要作者,你可以简单地在book__name查询:

authors = Author.objects.filter(book__name="some value") 

您可以使用.prefetch_related('book')预取书。如果你真的需要的两本书和作者的简单列表,你可以跳过prefetch_related和做到这一点:

books = Book.objects.filter(name="some value") 
authors = Author.objects.filter(book__in=books)