反向查找 Django 非对称 1:N 关系
Reverse lookup on a Django asymmetric 1:N relationship
在 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)
和少数objects定义如下:
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 的实体,或者任何 parent 得分小于 10 的实体,这很容易:
Entity.objects.filter(Q(score < 5) | Q(parent__score < 5))
如预期的那样,以上将与一个实体“a”完全匹配。但是,如果我想知道所有 top-level (parent == None) 得分超过 10 的实体,或者 children 得分超过 10 的实体, 如何定义查询?
Entity.objects.filter(parent=None).(Q(score > 10) | Q(?__score > 10))
我需要匹配的答案是 parent,而不是 child(我需要一个查询集,以便我可以根据需要对其进行优化)。如果我排除了 non-parent 个实体,那么我就无法确定要编写的查询。我应该写什么来代替上面的 ? 以便查询 returns 一个条目,“a”?
related_query_name
[Django docs] 是用于模型反向过滤器名称的名称。 related_query_name
的默认值是模型本身的小写名称,除非您指定 related_name
然后它默认为小写。因此,在您的过滤器中,您可以使用 entity
来访问相关的子项。此外,您提供的示例查询会引发错误,因为 Q(score < 5)
不是 而不是 您如何进行少于查询,您需要改用 __lt
。考虑到所有这些,您的查询应采用以下形式:
Entity.objects.filter(Q(score__gt=10) | Q(entity__score__gt=10), parent=None)
最好在外键上设置 related_name
和 related_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)
在 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)
和少数objects定义如下:
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 的实体,或者任何 parent 得分小于 10 的实体,这很容易:
Entity.objects.filter(Q(score < 5) | Q(parent__score < 5))
如预期的那样,以上将与一个实体“a”完全匹配。但是,如果我想知道所有 top-level (parent == None) 得分超过 10 的实体,或者 children 得分超过 10 的实体, 如何定义查询?
Entity.objects.filter(parent=None).(Q(score > 10) | Q(?__score > 10))
我需要匹配的答案是 parent,而不是 child(我需要一个查询集,以便我可以根据需要对其进行优化)。如果我排除了 non-parent 个实体,那么我就无法确定要编写的查询。我应该写什么来代替上面的 ? 以便查询 returns 一个条目,“a”?
related_query_name
[Django docs] 是用于模型反向过滤器名称的名称。 related_query_name
的默认值是模型本身的小写名称,除非您指定 related_name
然后它默认为小写。因此,在您的过滤器中,您可以使用 entity
来访问相关的子项。此外,您提供的示例查询会引发错误,因为 Q(score < 5)
不是 而不是 您如何进行少于查询,您需要改用 __lt
。考虑到所有这些,您的查询应采用以下形式:
Entity.objects.filter(Q(score__gt=10) | Q(entity__score__gt=10), parent=None)
最好在外键上设置 related_name
和 related_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)