Opened 8 years ago

Closed 2 years ago

#28078 closed Cleanup/optimization (invalid)

Can't use field as part of expression when annotate key shadows model field

Reported by: Pavel Patrin Owned by: nobody
Component: Database layer (models, ORM) Version: 1.10
Severity: Normal Keywords:
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Could not use fileld as part of expression when annotate key shadows model field

For example i have a model

    class MyModel(Model):
        grouping_field = TextField()
        amount_field_1 = IntegerField()
        amount_field_2 = IntegerField()


    queryset = MyModel.objects.values('grouping_field')

    # This is ok!
    queryset.annotate(amount_field_1=Sum('amount_field_1'))

    # This triggers error!
    # {FieldError}Cannot compute Sum('<CombinedExpression: F(amount_field_1) + F(amount_field_2)>'): '<CombinedExpression: ...>' is an aggregate
    queryset.annotate(
        amount_field_1=Sum('amount_field_1'),
        amount_field_2=Sum(F('amount_field_1') + F('amount_field_2')),
    )  

Change History (3)

comment:1 by Simon Charette, 8 years ago

While the exception is different this looks similar to #28072.

comment:2 by Tim Graham, 8 years ago

Summary: Could not use fileld as part of expression when annotate key shadows model fieldCan't use field as part of expression when annotate key shadows model field
Triage Stage: UnreviewedAccepted
Type: UncategorizedCleanup/optimization

I'm not sure what should be done here, accepting for further investigation.

comment:3 by Simon Charette, 2 years ago

Resolution: invalid
Status: newclosed

After further review I'm going to close this one as invalid.

If you shadow a field with an annotation (this seems to be only allowed here because values is used prior see #28072) then the ORM will default to the annotation override, F doesn't mean field reference it should have been name Ref (and Ref should have been named ResolvedRef).

If you want to keep referring to MyModel.amount_field_1 you must create an alias to it prior to shadowing it with your annotation

MyModel.objects.annotate(amount_field_1_alias=F("amount_field_1")).values(
    "grouping_field"
).annotate(
    amount_field_1=Sum("amount_field_1"),
    amount_field_2=Sum(F("amount_field_1_alias") + F("amount_field_2")),
)
Note: See TracTickets for help on using tickets.
Back to Top