Django的:多对多器的匹配对列表中的所有项目Django的:多对多器的匹配对列表中的所有项目(D

2019-05-12 02:25发布

我有这样一本书的模型:

class Book(models.Model):
    authors = models.ManyToManyField(Author, ...)
    ...

简而言之:

我想检索其作者是严格等于给定作者的书籍。 我不知道如果有,做一个单一的查询,但是任何建议将是有益的。

在长:

以下是我试过,(也无法运行得到一个AttributeError)

# A sample set of authors
target_authors = set((author_1, author_2))

# To reduce the search space, 
# first retrieve those books with just 2 authors.
candidate_books = Book.objects.annotate(c=Count('authors')).filter(c=len(target_authors))

final_books = QuerySet()
for author in target_authors:
    temp_books = candidate_books.filter(authors__in=[author])
    final_books = final_books and temp_books

...这里是我得到了什么:

AttributeError: 'NoneType' object has no attribute '_meta'

在一般情况下,我应该怎么查询与它的多对多字段包含了一组给定的对象为在我的情况下,约束模式?

PS:我发现了一些相关的SO问题,但未能得到明确的答案。 任何好的指针将有帮助。 谢谢。

Answer 1:

类似@ goliney的做法,我找到了解决办法。 不过,我认为,效率会得到提高。

# A sample set of authors
target_authors = set((author_1, author_2))

# To reduce the search space, first retrieve those books with just 2 authors.
candidate_books = Book.objects.annotate(c=Count('authors')).filter(c=len(target_authors))

# In each iteration, we filter out those books which don't contain one of the 
# required authors - the instance on the iteration.
for author in target_authors:
    candidate_books = candidate_books.filter(authors=author)

final_books = candidate_books


Answer 2:

您可以使用带Q对象的复杂查询

from django.db.models import Q
...
target_authors = set((author_1, author_2))
q = Q()
for author in target_authors:
    q &= Q(authors=author)
Books.objects.annotate(c=Count('authors')).filter(c=len(target_authors)).filter(q)


Answer 3:

Q()Q()不等于.filter()。过滤()。 他们生SQLS身在何处,通过使用Q随&不同,它的SQL只需添加类似条件WHERE "book"."author" = "author_1" and "book"."author" = "author_2" 。 它应该返回空的结果。

唯一的解决办法就是通过链接过滤器,以形成一个SQL与内部联接上相同的表: ... ON ("author"."id" = "author_book"."author_id") INNER JOIN "author_book" T4 ON ("author"."id" = T4."author_id") WHERE ("author_book"."author_id" = "author_1" AND T4."author_id" = "author_1")



Answer 4:

我遇到了同样的问题,来到了同样的结论为iuysal,直到我不得不做一个中型搜索(与1000个记录有150种滤镜我请求将超时)。

在我的特殊情况下,搜索会导致没有记录,因为单个记录将与所有150种滤镜排列的几率是非常罕见的,可以申请更多的过滤器,以节省之前通过验证,有在QuerySet的记录得到解决性能问题时间。

# In each iteration, we filter out those books which don't contain one of the 
# required authors - the instance on the iteration.
for author in target_authors:
   if candidate_books.count() > 0:
      candidate_books = candidate_books.filter(authors=author)

出于某种原因,Django的过滤器适用于空查询集。 但是,如果优化是正确然而,一个使用准备的QuerySet应用和正确应用指标是必要的。



文章来源: Django: ManyToMany filter matching on ALL items in a list