1

I have a Django model that has a NumberVal field which is models.FloatField().

Then I need to annotate the queryset objects like so .annotate(numberval_as_text=str(OuterRef("NumberVal"))) - the same value, but as a string except for the fact that this throws QuerySet.annotate() received non-expression(s): OuterRef(NumberVal) error which is clearly right but it demonstrates the point.

I need this because this annotation is followed by an extensive second annotation where I need this numberval_as_text in subquery filters.

Any hint would be appreciated.

David Louda
  • 498
  • 5
  • 19

2 Answers2

2

Calling str on an object obviously will give you a string representation of the object, hence you get the error. If one wants to type case something, they can use the Cast database function [Django docs]:

from django.db.models import CharField
from django.db.models.functions import Cast


queryset.annotate(numberval_as_text=Cast(OuterRef("NumberVal"), output_field=CharField(max_length=256)))

Note: Unless this annotation is in a subquery, you want to use F("NumberVal") (from django.db.models import F) instead of OuterRef("NumberVal")

Abdul Aziz Barkat
  • 19,475
  • 3
  • 20
  • 33
  • Great answer, thank you. Final solution that worked looks like this `for_value_exists_related_parameter_of_a_different_type=Subquery( agr_distribution_product_parameters.annotate(numberval_as_text=Cast("NumberVal", output_field=CharField(max_length=256))).filter( Q(ProductId=object_id) & (Q(TextVal=OuterRef("DistributionParameterValueId__Code")) | Q(TextVal=OuterRef("DistributionParameterValueId__Value")) | Q(numberval_as_text=OuterRef("DistributionParameterValueId__Code")) | Q(numberval_as_text=OuterRef("DistributionParameterValueId__Value")))).values('id')[:1]` – David Louda May 26 '21 at 07:40
1

You don't need to use OuterRef. You can just use plain cast with annotation.

from django.db import models
from django.db.models.functions import Cast


qs.annotate(numberval_as_text=Cast('NumberVal', output_field=models.CharField()))
Nafees Anwar
  • 6,324
  • 2
  • 23
  • 42