#24508 closed Bug (fixed)
F() object operations do not correcly reflect with annotate
Reported by: | mijamo | Owned by: | Josh Smeaton |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.8rc1 |
Severity: | Release blocker | Keywords: | F() |
Cc: | Triage Stage: | Ready for checkin | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Hello,
This ticket is related to the 1.8 new feature of using various F operations within an annotation.
I have spotted 2 problems so far :
1) F('field') * 2 apparently isn't the same as 2 * F('field')
Description of the problem :
SomeModel.objects.all().annotate(computed = F('some_field') * 2) Works as expected SomeModel.objects.all().annotate(computed = 2 * F('some_field')) E: django.core.exceptions.FieldError: Expression contains mixed types. You must set output_field SomeModel.objects.all().annotate(computed = Expression(2 * F('some_field'), output_field = FloatField())) E : TypeError: __init__() got multiple values for argument 'output_field'
The last exception, about init, is the most problematic as it doesn't state anything about where is the problem (no info in the traceback)
2) When a F object is added to None, it causes a conflict
Description of the problem :
SomeModel.objects.all().annotate(computed = F('some_field') + None) Works as expected SomeModel.objects.all().annotate(computed = None + F('some_field')) E: django.core.exceptions.FieldError: Expression contains mixed types. You must set output_field SomeModel.objects.all().annotate(computed = Expression(None + F('some_field'), output_field = FloatField())) E : TypeError: __init__() got multiple values for argument 'output_field'
You might wonder why there would be a None in the construction. For me it is because I am building the object in a for, so I have something like this :
annotation = None for field in fields_to_be_added: annotation += F(field) SomeModel.objects.all().annotate(annotation)
Change History (5)
comment:1 by , 10 years ago
Summary: | F() object operations correcly reflecting with annotate → F() object operations do not correcly reflect with annotate |
---|
comment:2 by , 10 years ago
comment:3 by , 10 years ago
Has patch: | set |
---|---|
Owner: | changed from | to
Status: | new → assigned |
Triage Stage: | Unreviewed → Ready for checkin |
Turned out this wasn't so difficult to fix. I've opened a PR https://github.com/django/django/pull/4352
I can't see there being in compatibility concerns. The behaviour is now inline with filter(a=2+F('b')
.
Part of this problem will be solved by https://github.com/django/django/pull/4349
Where
ExpressionWrapper
replaces your previous (and incorrectly documented)Expression
.The second part, where you get different results depending on which node is left or right could possibly be fixed, but we may not be able to if it results in backwards compatibility problems.
What is the field type of
some_field
in your example? An integer or float?