【问题标题】:Reverse lookup on a Django asymmetric 1:N relationship反向查找 Django 非对称 1:N 关系
【发布时间】:2021-06-10 16:31:17
【问题描述】:

在 Django 中,与 1:N 关系的反向查找关联的查询管理器是什么?

假设我有一个简单的 Django 模型:

class Entity(models.Model):
    name = models.CharField(max_length=100, primary_key=True)
    score = models.IntegerField(default=0)
    parent = models.ForeignKey("self", null=True, default=None, on_delete=models.CASCADE)

还有一些对象定义如下:

a = Entity.objects.create(name="A", score=5)
b = Entity.objects.create(name="B", score=10, parent=a)
c = Entity.objects.create(name="C", score=11, parent=a)

如果我想找出所有得分低于 10 的实体,或任何其父级得分低于 10 的实体,这很容易:

Entity.objects.filter(Q(score < 5) | Q(parent__score < 5))

如预期的那样,上面将完全匹配一个实体“a”。但是,如果我想知道所有得分超过 10 的顶级(父 == 无)实体,或者谁有得分超过 10 的孩子,我该如何定义查询?

Entity.objects.filter(parent=None).(Q(score > 10) | Q(?__score > 10))

我需要匹配的答案是父母,而不是孩子(我需要一个查询集,以便我可以根据需要对其进行优化)。如果我排除非父实体,那么我无法弄清楚要编写的查询。我应该写什么来代替上面的 ? 以便查询返回一个条目“a”?

【问题讨论】:

    标签: django django-models django-queryset


    【解决方案1】:

    related_query_name [Django docs] 是用于模型的反向过滤器名称的名称。 related_query_name 的默认值是模型本身的小写名称,除非您指定 related_name,否则它默认为该名称。因此,在您的过滤器中,您可以使用entity 来访问相关的孩子。此外,您提供的示例查询将引发错误,因为Q(score &lt; 5) 不是不是您如何进行少于查询,您需要改用__lt。考虑到所有这些,您的查询应采用以下形式:

    Entity.objects.filter(Q(score__gt=10) | Q(entity__score__gt=10), parent=None)
    

    最好在外键上设置related_namerelated_query_name 以更有意义:

    class Entity(models.Model):
        name = models.CharField(max_length=100, primary_key=True)
        score = models.IntegerField(default=0)
        parent = models.ForeignKey("self", null=True, default=None, on_delete=models.CASCADE, related_name="children", related_query_name="child")
    

    现在您可以将查询编写为:

    Entity.objects.filter(Q(score__gt=10) | Q(child__score__gt=10), parent=None)
    

    【讨论】:

      猜你喜欢
      • 2016-09-15
      • 2019-05-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-07
      • 2014-05-27
      • 1970-01-01
      • 2020-01-17
      相关资源
      最近更新 更多