pythondjangodjango-templatesdjango-querysetchoicefield

django: choice display with queryset values


I want to use get_status_display on template, from a queryset with just some fields from model.

I have a model with a choices field (status).

class Operation(models.Model, ModelMixin):
    operation_area = models.ForeignKey('operations.OperationArea', null=True)

    created = models.DateTimeField(auto_now=True)
    indication = models.NullBooleanField()
    observation = models.TextField(blank=True, null=True)
    rate = models.IntegerField(blank=True, null=True)
    scheduling = models.DateTimeField(blank=True, null=True)
    status = models.IntegerField(choices=OPERATION_TYPE)

class OperationArea(models.Model, ModelMixin):
    campaign = models.ForeignKey('campaigns.Campaign')
    person = models.ForeignKey('registrations.Person')
    user = models.ForeignKey('authentication.User')

    area = models.CharField(max_length=1, choices=OPERATION_AREA)

My query is:

Operation.objects.filter(operation_area__user=user).values('id', 'created', 'operation_area__person__name', 'status')

From this a get a dict, but get_FOO_dislpay is a instance method and don't works on a dict. I don't want to use .only() because he brings operation_area object and to get the person.name he makes another query, like this operation.operation_area.person.name. Any thoughts how to work with one query and get_FOO_display?


Solution

  • I think annotate() is what you looking for.

    Annotates each object in the QuerySet with the provided list of query expressions. An expression may be a simple value, a reference to a field on the model (or any related models), or an aggregate expression (averages, sums, etc.) that has been computed over the objects that are related to the objects in the QuerySet.

    Each argument to annotate() is an annotation that will be added to each object in the QuerySet that is returned.

    The aggregation functions that are provided by Django are described in Aggregation Functions below.

    Annotations specified using keyword arguments will use the keyword as the alias for the annotation. Anonymous arguments will have an alias generated for them based upon the name of the aggregate function and the model field that is being aggregated. Only aggregate expressions that reference a single field can be anonymous arguments. Everything else must be a keyword argument.

    You should use:

    operations.annotate(person_name=F('operation_area__person__name')) 
    

    Take a look at https://docs.djangoproject.com/en/2.0/ref/models/querysets/#annotate.