【问题标题】:Django filter many-to-many with containsDjango 使用包含过滤多对多
【发布时间】:2011-05-29 07:37:42
【问题描述】:

我正在尝试通过多对多关系过滤一堆对象。因为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)

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

感谢您的帮助。

【问题讨论】:

    标签: python django django-models many-to-many django-orm


    【解决方案1】:

    你有没有尝试过这样的事情:

    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)
    

    【讨论】:

    • 这似乎不起作用。由于 self.role.id 只是一个 int 而 trigger_roles 是它们的列表,我需要一个倒置的,比如包含,但我发现,包含仅用于字符串。
    • 第二个例子应该工作。如果self.role.id 中的值是触发器角色之一,则该过滤器应拉取所有工作流,其中触发器角色之一是self.role.id 中的值。基本上,这将与“包含”函数完全一样。除非我们都错过了什么。
    • @Jordan Reiter:“contains”在 sql 中被转换为“like”,这不是 OP 想要的,我认为他已经指出了这一点,另一方面,“exact”被转换为“= " 或 "是" 这是这里的想法。
    • aww .. 抱歉,您的第二个解决方案运行良好 :) 我这边有一点配置失误。谢谢你们这拯救了我的一天;-)
    • @SeanLetendre:它是应用的过滤器之一(参见示例中Workflow 模型上的allowed 属性)。这意味着没有上下文。
    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

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

      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)
        

        【讨论】:

          猜你喜欢
          • 2021-09-29
          • 2019-03-28
          • 1970-01-01
          • 2020-05-27
          • 2011-01-14
          • 2020-03-16
          • 1970-01-01
          • 2018-09-09
          • 2016-06-19
          相关资源
          最近更新 更多