Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do many-to-many Django query to find book with 2 given authors?

Tags:

I have a query that requires to filter exactly 2 authors with the ID

Theoretically,

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

which is not possible.

How can I solve this problem?

Cheers, Mickey

like image 512
Mickey Cheong Avatar asked Mar 14 '11 17:03

Mickey Cheong


People also ask

What is _SET all () in Django?

_set is associated with reverse relation on a model. Django allows you to access reverse relations on a model. By default, Django creates a manager ( RelatedManager ) on your model to handle this, named <model>_set, where <model> is your model name in lowercase.

What does .values do in Django?

Return Specific Columns The values_list() method allows you to return only the columns that you specify.

How do you count in Django ORM?

Use Django's count() QuerySet method — simply append count() to the end of the appropriate QuerySet. Generate an aggregate over the QuerySet — Aggregation is when you "retrieve values that are derived by summarizing or aggregating a collection of objects." Ref: Django Aggregation Documentation.


1 Answers

Not intuitive at first but the answer is right in front of us.

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

If you want an exact match, you could potentially further filter this result by those items that only have exactly 2 authors.

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

If you want exact matches dynamically, how about something like this?:

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. 
like image 124
Yuji 'Tomita' Tomita Avatar answered Sep 21 '22 13:09

Yuji 'Tomita' Tomita