【问题标题】:Django order a query by instance of ManyToManyDjango通过ManyToMany的实例订购查询
【发布时间】:2021-05-27 07:36:09
【问题描述】:

我有一个模型 A 和 B 的外键:

class A(models.Model):
    b = models.ForeignKey(B, on_delete=models.CASCADE)

ManyToMany 关系带有一个额外的字段,该字段对任何 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)

我需要使用给定 C 实例的 B2C 权重来订购 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()ExpressionWrapperSubQueryannotate,但我不知道如何使用它们来解决我的问题。

感谢阅读:)

【问题讨论】:

    标签: python django postgresql many-to-many


    【解决方案1】:

    正如您已经注意到的,您需要使用Subquery [Django docs]annotate 的权重。您可以在过滤时使用OuterRef 引用外部查询b,也可以使用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')
    

    【讨论】:

    • 完美,正是我需要的!谢谢;)
    猜你喜欢
    • 2014-06-20
    • 2012-01-18
    • 1970-01-01
    • 1970-01-01
    • 2013-03-25
    • 2020-09-24
    • 2014-02-11
    • 2017-07-30
    • 2011-12-21
    相关资源
    最近更新 更多