Как применить фильтр к полю ManyToManyField в django так, чтобы несколько значений поля соответствовали условию?

class Publication(models.Model):
    title = models.CharField(max_length=30)


class Article(models.Model):
    headline = models.CharField(max_length=100)
    publications = models.ManyToManyField(Publication)

p1 = Publication.objects.create(title='The Python Journal')
p2 = Publication.objects.create(title='Science News')
p3 = Publication.objects.create(title='Science Weekly')

Я хочу отфильтровать статьи, опубликованные в p1 и p3. Они могут публиковаться или не публиковаться в других изданиях, но они должны быть опубликованы в p1 и p3.

В тестах many-to-many и many-to-one есть много примеров фильтров в стиле FOO__in=.... Вот синтаксис для вашей конкретной проблемы:

# filtering on a few publications, by id
articles = Article.objects.filter(publications__in=[<id1>, <id2>, <id3>])
# and by publication object (object gets converted to pk under the covers)
articles = Article.objects.filter(publications__in=[publication1, publication2, publication3])
# and by publication title
articles = Article.objects.filter(publications__title__icontains='Science')

icontains используется i для нечувствительности к регистру, contains для того, что слово содержит эти буквы и, возможно, их меньше или больше.

Синтаксис двойного подчеркивания (__) используется повсеместно при работе с queryset.

Если вы связываете несколько вызовов filter(), они должны вести себя как соединенные с AND:

articles = Article.objects.filter(publications=p1).filter(publications=p3).distinct()

У меня была похожая проблема, когда некоторые пользователи имели бесплатную и платную роль, поэтому мне нужно было выбрать пользователей, имеющих две определенные роли в поле many to many.

Я сделал что-то вроде этого, работает как шарм

roles = [premium_role, default_role]

DiscordUser.objects.filter(guild=guild)
    .annotate(freemium=Count('roles', filter=Q(roles__in=roles)))
    .filter(freemium=2)
    .values('id')
Вернуться на верх