Django过滤器包含对多对多


87

我试图通过多对多关系过滤一堆对象。因为该trigger_roles字段可能包含多个条目,所以我尝试了contains过滤器。但是由于它被设计为与字符串一起使用,我几乎无助于我如何过滤这种关系(您可以忽略values_list()atm。)。

此功能附加到用户配置文件:

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)

尽管解决方案可能很简单,但是我的大脑不会告诉我。

谢谢你的帮助。

Answers:


109

您是否尝试过以下方法:

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

或只是self.role.id不是pk列表:

module.workflow_set.filter(trigger_roles__id__exact=self.role.id, allowed=True)

1
这似乎不起作用。由于self.role.id只是一个int,而trigger_roles是它们的列表,因此,我需要一个反向输入,例如contains,但是正如我发现的那样,contains仅用于字符串。
Grave_Jumper 2010年

8
第二个例子应该起作用。如果in的值self.role.id是触发角色之一,则该过滤器应拉出所有触发触发作用之一为in中的值的工作流程self.role.id。基本上,这将完全类似于“包含”功能。除非我们都缺少某些东西。
Jordan Reiter 2010年

@Jordan Reiter:“包含”在sql中被转换为“ like”,这不是OP想要的,我认为他已经指出了这一点,另一方面,“ exact”被转换为“ =”或“ is”,即这里的想法。
mouad 2010年

@Grave_Jumper:在这里看看(djangoproject.com/documentation/models/many_to_many),在使用ManytoMany Field时,您可以找到一些示例,希望这对您有帮助,如果我的回答不是:)
10年

1
aww ..很抱歉,您的第二个解决方案运行效果很好:)我这边有点错过配置。谢谢大家,这挽救了我的一天;-)
Grave_Jumper 2010年

18

实现此目的的最简单方法是检查中的整个实例(而不是ID)是否相等ManyToManyField。看起来实例是否在多对多关系中。例:

module.workflow_set.filter(trigger_roles=self.role, allowed=True)

6

我知道这是一个老问题,但看来OP从未完全得到他所寻找的答案。如果要比较两组ManyToManyFields,诀窍是使用__in运算符,而不是contains。因此,例如,如果您有一个“事件”模型eventgroups,并且在字段上有ManyToMany可以将其“分组” ,并且您的User模型(显然)附加到Group,则可以这样查询:

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


4

在第一个示例中,奇异性几乎是正确的。您只需要确保它是一个列表即可。第二个例子,检查trigger_roles__id__exact是一个更好的解决方案。

module.workflow_set.filter(trigger_roles__in=[self.role.id],allowed=True)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.