Django 通过 ManyToMany 实例对查询进行排序
Django order a query by instance of ManyToMany
我有一个模型 A,其外键指向 B:
class A(models.Model):
b = models.ForeignKey(B, on_delete=models.CASCADE)
一个多对多关系,带有一个额外的字段,对任何 B 和 C 关系进行加权:
class B2C(models.Model):
b = models.ForeignKey(B, on_delete=models.CASCADE)
c = models.ForeignKey(C, on_delete=models.CASCADE)
weight = models.IntegerField(default=0)
我需要使用 B2C 的权重为给定的 C 实例订购 A 模型 (A.objects.filter(...))。
我只能做一个 A 实例:
# Example of C instance
c = C.objects.get(pk=1)
# Single instance of A
a = A.objects.get(pk=1)
# Getting the weight for this instance
# A => B => B2C WHERE metier=metier
weight = a.b.b2c_set.get(c=c)
但我不知道如何在查询集上应用它(比如在 annotate
中使用它)。
在我的研究过程中,我发现了论文 F()
、ExpressionWrapper
、SubQuery
、annotate
,但我不知道如何使用它们来解决我的问题.
感谢阅读:)
正如您已经注意到的,您需要使用 Subquery
[Django docs] to annotate
the weight. You can use OuterRef
to refer to the outer queries b
while filtering and also use Coalesce
[Django docs] 以防万一以提供默认值:
from django.db.models import OuterRef, Subquery
from django.db.models.functions import Coalesce
weight_subquery = B2C.objects.filter(b=OuterRef('b'), c=given_c_instance)
queryset = A.objects.annotate(
weight=Coalesce(Subquery(weight_subquery.values('weight')[:1]), 0)
).order_by('weight')
我有一个模型 A,其外键指向 B:
class A(models.Model):
b = models.ForeignKey(B, on_delete=models.CASCADE)
一个多对多关系,带有一个额外的字段,对任何 B 和 C 关系进行加权:
class B2C(models.Model):
b = models.ForeignKey(B, on_delete=models.CASCADE)
c = models.ForeignKey(C, on_delete=models.CASCADE)
weight = models.IntegerField(default=0)
我需要使用 B2C 的权重为给定的 C 实例订购 A 模型 (A.objects.filter(...))。
我只能做一个 A 实例:
# Example of C instance
c = C.objects.get(pk=1)
# Single instance of A
a = A.objects.get(pk=1)
# Getting the weight for this instance
# A => B => B2C WHERE metier=metier
weight = a.b.b2c_set.get(c=c)
但我不知道如何在查询集上应用它(比如在 annotate
中使用它)。
在我的研究过程中,我发现了论文 F()
、ExpressionWrapper
、SubQuery
、annotate
,但我不知道如何使用它们来解决我的问题.
感谢阅读:)
正如您已经注意到的,您需要使用 Subquery
[Django docs] to annotate
the weight. You can use OuterRef
to refer to the outer queries b
while filtering and also use Coalesce
[Django docs] 以防万一以提供默认值:
from django.db.models import OuterRef, Subquery
from django.db.models.functions import Coalesce
weight_subquery = B2C.objects.filter(b=OuterRef('b'), c=given_c_instance)
queryset = A.objects.annotate(
weight=Coalesce(Subquery(weight_subquery.values('weight')[:1]), 0)
).order_by('weight')