Django使用contains过滤多对多

Gra*_*per 68 python django many-to-many django-models django-orm

我试图通过多对多关系过滤一堆对象.因为trigger_roles字段可能包含多个条目,所以我尝试了包含过滤器.但是因为它被设计为与字符串一起使用,我几乎无能为力地过滤这种关系(你可以忽略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)
Run Code Online (Sandbox Code Playgroud)

我的工作流模型看起来像这样(简化):

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)
Run Code Online (Sandbox Code Playgroud)

虽然解决方案可能很简单,但我的大脑不会告诉我.

谢谢你的帮助.

mou*_*uad 90

你尝试过这样的事情:

module.workflow_set.filter(trigger_roles__in=[self.role], allowed=True)
Run Code Online (Sandbox Code Playgroud)

或者只是如果self.role.id不是pks列表:

module.workflow_set.filter(trigger_roles__id__exact=self.role.id, allowed=True)
Run Code Online (Sandbox Code Playgroud)

  • 第二个例子*应该*工作.如果`self.role.id`中的值是触发器角色之一,那么该过滤器应该拉出所有工作流,其中一个触发器角色是`self.role.id`中的值.基本上这将表现得像"包含"功能.除非我们都缺少一些东西. (5认同)
  • 这似乎不起作用。由于 self.role.id 只是一个 int 而 trigger_roles 是它们的列表,因此我需要一个倒置的,就像 contains 一样,但据我发现, contains 仅适用于字符串。 (2认同)

Cau*_*ons 15

实现这一目标的最简单方法是检查整个实例(而不是id)的相等性ManyToManyField.这看起来实例是在多对多的关系中.例:

module.workflow_set.filter(trigger_roles=self.role, allowed=True)
Run Code Online (Sandbox Code Playgroud)


sha*_*ker 8

我知道这是一个老问题,但看起来 OP 从来没有得到他想要的答案。如果您要比较两组 ManyToManyFields,诀窍是使用__in运算符,而不是contains. 因此,例如,如果您有一个“事件”模型,字段上的“多对多”到“组” eventgroups,并且您的用户模型(显然)附加到组,您可以这样查询:

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


Jos*_*ton 5

第一个例子的奇点几乎是正确的。你只需要确保它是一个列表。第二个例子,检查trigger_roles__id__exact是一个更好的解决方案。

module.workflow_set.filter(trigger_roles__in=[self.role.id],allowed=True)
Run Code Online (Sandbox Code Playgroud)