Фильтр Django «многие ко многим» содержит - PullRequest
65 голосов
/ 22 декабря 2010

Я пытаюсь отфильтровать кучу объектов через отношение многие ко многим.Поскольку поле trigger_roles может содержать несколько записей, я пробовал фильтр содержит.Но так как он предназначен для использования со строками, я в значительной степени беспомощен, как я должен фильтровать это отношение (вы можете игнорировать atms values_list ().)1003 *

def getVisiblePackages(self):
    visiblePackages = {}   
    for product in self.products.all():
        moduleDict = {}
        for module in product.module_set.all():
            pkgList = []
            involvedStatus = module.workflow_set.filter(trigger_roles__contains=self.role.id,allowed=True).values_list('current_state', flat=True)

Моя модель рабочего процесса выглядит так (упрощенно):

class Workflow(models.Model):
    module = models.ForeignKey(Module)
    current_state = models.ForeignKey(Status)
    next_state = models.ForeignKey(Status)
    allowed = models.BooleanField(default=False)
    involved_roles = models.ManyToManyField(Role, blank=True, null=True)
    trigger_roles = models.ManyToManyField(Role, blank=True, null=True)

Хотя решение может быть довольно простым, мой мозг не скажет мне.за вашу помощь.

Ответы [ 4 ]

86 голосов
/ 22 декабря 2010

Вы пробовали что-то вроде этого:

module.workflow_set.filter(trigger_roles__in=[self.role], allowed=True)

или просто, если self.role.id не список pks:

module.workflow_set.filter(trigger_roles__id__exact=self.role.id, allowed=True)
14 голосов
/ 19 августа 2013

Самый простой подход для достижения этой цели - проверка на равенство по всему экземпляру (вместо идентификатора) в ManyToManyField. Это выглядит, если экземпляр находится внутри отношения многих ко многим. Пример:

module.workflow_set.filter(trigger_roles=self.role, allowed=True)
4 голосов
/ 22 декабря 2010

сингулярность почти соответствует первому примеру.Вам просто нужно убедиться, что это список.Второй пример, проверка trigger_roles__id__exact является лучшим решением.

module.workflow_set.filter(trigger_roles__in=[self.role.id],allowed=True)
3 голосов
/ 01 июня 2016

Я знаю, что это старый вопрос, но похоже, что ОП так и не получил ответ, который искал.Если у вас есть два набора полей ManyToManyFF, которые вы хотите сравнить, уловка заключается в использовании оператора __in, а не contains.Так, например, если у вас есть модель «Событие» с ManyToMany для «Группа» в поле eventgroups, и ваша пользовательская модель (очевидно) присоединяется к Группе, вы можете сделать запрос следующим образом:

Event.objects.filter(eventgroups__in=u.groups.all())

...