Django queryset for Case object and When Object, ---

Viewed 1286

I would to get your help on the following : I have two models Parent model and a Child Model:

class Rate(models.Model):
        RATE_VOLTAGE_CHOICES = (
            (BAJA_TENSION, "Low tension"),
            (MEDIA_TENSION, "Mid tension"),
            (ALTA_TENSION, "High tension")
        )
        rate_type = models.CharField(max_length=1, choices=RATE_TYPE_CHOICES, default="0")

class ParentRate(models.Model):
    rate = models.ForeignKey(Rate, on_delete=models.SET_NULL, blank=True, null=True

)

so front-end wants to "filter" rate_type choice by Low tension, Mid Tension, and High tension as strings, they send strings so I am trying to use When Case object so I can filter then:

rates = ParentRate.objects.annotate(rate_voltage=Case(
                    When(rate__rate_type=Rate.BAJA_TENSION, then=Value('Low tension')),
                    When(rate__rate_type=Rate.MEDIA_TENSION, then=Value('Mid tension')),
                    When(rate__rate_type=Rate.ALTA_TENSION, then=Value('High tension')),
                    default=Value('Low tension'),
                )

            )

but I am getting the following error:

django.core.exceptions.FieldError: Cannot resolve expression type, unknown output_field
2 Answers

You need to add an output_field to your query like this example:

from django.db.models import fields


rates = ParentRate.objects.annotate(rate_voltage=Case(
                    When(rate__rate_type=Rate.BAJA_TENSION, then=Value('Low tension')),
                    When(rate__rate_type=Rate.MEDIA_TENSION, then=Value('Mid tension')),
                    When(rate__rate_type=Rate.ALTA_TENSION, then=Value('High tension')),
                    default=Value('Low tension'),
                    output_field=fields.CharField()  # if the output field is a string
                )

            )

For more informations: Django docs: Aggregate() expressions

As documented in Aggregate() expression

The output_field argument requires a model field instance, like IntegerField() or BooleanField(), into which Django will load the value after it’s retrieved from the database.

Note that output_field is only required when Django is unable to determine what field type the result should be. Complex expressions that mix field types should define the desired output_field. For example, adding an IntegerField() and a FloatField() together should probably have output_field=FloatField() defined.

In your case it would be CharField

rates = ParentRate.objects.annotate(rate_voltage=Case(
                    When(rate__rate_type=Rate.BAJA_TENSION, then=Value('Low tension')),
                    When(rate__rate_type=Rate.MEDIA_TENSION, then=Value('Mid tension')),
                    When(rate__rate_type=Rate.ALTA_TENSION, then=Value('High tension')),
                    default=Value('Low tension'),
                    output_field=CharField()
                ),

            )
Related