Django:条件表达式

时间:2016-03-21 17:12:13

标签: python django django-orm

我有以下型号:

class Agreement(models.Model):
    ...
    organization = models.ForeignKey("Organization")

class Signed_Agreement(models.Model):
    agreement = models.ForeignKey("Agreement")
    member = models.ForeignKey("Member")

我要做的是获取特定组织的所有协议列表(自组织),并使用有关是否已由特定成员签署的信息(自我成员)注释每个协议。

如果协议已经签署,那么特定协议和成员就存在Signed_Agreement实例。

如何为此编写查询?

到目前为止,这是我的努力:

from django.db.models import When, F, Q, Value

def get_queryset(self):

    agreements = _agreement_model.Agreement.objects.filter(
        organization=self.organization
    ).annotate(
        signed=When(Q(signed_agreement__member=self.member), then=Value(True))
    ).order_by(
        'name'
    )

    return agreements

这不会产生正确的结果。

任何帮助将不胜感激。提前谢谢。

2 个答案:

答案 0 :(得分:11)

我想你想在这里使用Case

def get_queryset(self):

    agreements = _agreement_model.Agreement.objects.filter(
        organization=self.organization
    ).annotate(
        signed=Case(When(signed_agreement__member=F('member')),
                    then=Value(True),
                    default=Value(False),
                    output_field=BooleanField()
    ).order_by(
        'name'
    )

    return agreements

<强>更新

根据评论,在Django的更高版本中似乎必须在then

中传递When
def get_queryset(self):

    agreements = _agreement_model.Agreement.objects.filter(
        organization=self.organization
    ).annotate(
        signed=Case(When(signed_agreement__member=F('member'), 
                         then=Value(True)
                    ),
                    default=Value(False),
                    output_field=BooleanField()
    ).order_by(
        'name'
    )

    return agreements

答案 1 :(得分:2)

通过Django 1.11.6,我接受的答案对我不起作用。我必须放then inside When才能使它发挥作用。

from django.db.models import Case, When, F, BooleanField


def get_queryset(self):
    agreements = _agreement_model.Agreement.objects.filter(
        organization=self.organization
    ).annotate(
        signed=Case(
            When(
                signed_agreement__member=F('member'),
                then=True
            ),
            default=False,
            output_field=BooleanField()
        )
    ).order_by(
        'name'
    )