Как сделать запрос Django «многие ко многим», чтобы найти книгу с двумя авторами? - PullRequest
14 голосов
/ 14 марта 2011

У меня есть запрос, который требует фильтрации ровно 2 авторов с идентификатором

Теоретически,

Book.objects.filter(author__id=1, author__id=2). 

, что невозможно.

Как я могу решить эту проблему?

Ура, Mickey

Ответы [ 3 ]

37 голосов
/ 14 марта 2011

Сначала не интуитивно понятно, но ответ прямо перед нами.

Book.objects.filter(author__id=1).filter(author__id=2)

Если вам нужно точное совпадение, вы можете дополнительно отфильтровать этот результат по тем элементам, которые имеют ровно 2 автора.

Book.objects.annotate(count=Count('author')).filter(author__id=1)\
                .filter(author__id=13).filter(count=2)

Если вам нужны динамические точные совпадения, как насчет чего-то подобного?

def get_exact_match(model_class, m2m_field, ids):
    query = model_class.objects.annotate(count=Count(m2m_field))\
                .filter(count=len(ids))
    for _id in ids:
        query = query.filter(**{m2m_field: _id})
    return query

matches = get_exact_match(MyModel, 'my_m2m_field', [1, 2, 3, 4])

# matches is still an unevaluated queryset, so you could run more filters
# without hitting the database.
0 голосов
/ 14 марта 2011

Q объектов помогут вам. Docs

Book.objects.filter(Q(author__id=1) & Q(author__id=2))
0 голосов
/ 14 марта 2011

Вы можете использовать запрос "IN". Django Docs

Book.objects.filter(author__id__in=[1,2])

...