Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django: conditional expression

I have the following models:

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

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

What I'm trying to do is get a list of all the agreements for a particular organization (self.organization) and annotate each agreement with information about whether or not it has been signed by a particular member (self.member).

If the Agreement has been signed, then there exists an instance of Signed_Agreement for the particular agreement and member.

How do I write a query for this?

Here's my effort so far:

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

This is not producing the correct results.

Any help would be appreciated. Thanks in advance.

like image 815
Ashish Acharya Avatar asked Mar 21 '16 17:03

Ashish Acharya


1 Answers

I think you want to be using a Case here.

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

UPDATE

Per comments it appears that in later versions of Django that the then must be passed in the 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
like image 53
sedavidw Avatar answered Sep 19 '22 15:09

sedavidw