1

I have the following model

class Status(object):
    FIRST_STATUS = 'FS'
    SECOND_STATUS = 'SS'

    CHOICES = ((FIRST_STATUS, 'First Status'), (SECOND_STATUS, 'Second Status')

class MyModel(models.Model):
    status = models.CharField(max_length=2, choices=Status.CHOICES)

I'm trying to annotate the status field so that the results will hold the readable value and not the status code. This is what i was trying to do:

MyModel.objects.annotate(status=Case(When(status=Status.FIRST_STATUS, then='First Status'), When(status=Status=SECOND_STATUS, then='Second Status'), output_field=CharField())).values('status')

The result was an exception:

`ValueError: The annotation 'status' conflicts with a field on the model.`<br/>
Which was not surprising because of [this][1] but what is, is that i can do this:<br/><br/>      


MyModel.objects.extra(select={'status': "CASE WHEN status='FS' THEN 'First Status' WHEN status='SS' THEN 'Second Status' ELSE 'Unknown status' END"}).values('status')

Why put the restriction on annotate and not validate the same behavior in extra? Is there any way of overriding the restriction on annotate and save me of building the query manually?

Aniket Pawar
  • 2,641
  • 19
  • 32
Mr T.
  • 4,278
  • 9
  • 44
  • 61

1 Answers1

1

Don't use status in the aggregate, try:

MyModel.objects.annotate(
    status_display=Case(
        When(status=Status.FIRST_STATUS, then='First Status'), 
        When(status=Status.SECOND_STATUS, then='Second Status'),
    ),
    output_field=CharField()
).values('status_display')

Even better: you don't need the Case-When nor the Status class. Django can handle that:

in models.py:

class MyModel(models.Model):
    FIRST_STATUS = 'FS'
    SECOND_STATUS = 'SS'
    CHOICES = (
        (FIRST_STATUS, 'First Status'), 
        (SECOND_STATUS, 'Second Status')
    )
    status = models.CharField(max_length=2, choices=CHOICES)

then:

my_models = MyModel.objects.all()  # Or filter or any QuerySet
for model in my_models:
    status_description = model.get_status_display()

Check here for more information.

alfonso.kim
  • 2,844
  • 4
  • 32
  • 37