#24420 closed Bug (fixed)
Can't order_by annotated field if annotated field uses conditional expression
| Reported by: | Kris Fields | Owned by: | Josh Smeaton |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | 1.8beta1 |
| Severity: | Normal | Keywords: | order_by, annotation, conditional expression |
| 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
Continuing with the Client example on https://docs.djangoproject.com/en/dev/ref/models/conditional-expressions/
from django.db import models
class Client(models.Model):
REGULAR = 'R'
GOLD = 'G'
PLATINUM = 'P'
ACCOUNT_TYPE_CHOICES = (
(REGULAR, 'Regular'),
(GOLD, 'Gold'),
(PLATINUM, 'Platinum'),
)
name = models.CharField(max_length=50)
registered_on = models.DateField()
account_type = models.CharField(
max_length=1,
choices=ACCOUNT_TYPE_CHOICES,
default=REGULAR,
)
Client.objects.annotate(
discount=Case(
When(account_type=Client.GOLD, then=Value('5%')),
When(account_type=Client.PLATINUM, then=Value('10%')),
default=Value('0%'),
output_field=CharField(),
),
).order_by('discount')
Error is:
<repr(<django.db.models.query.QuerySet at 0x10afaef10>) failed: AttributeError: 'WhereNode' object has no attribute 'resolve_expression'>
Change History (5)
comment:1 by , 11 years ago
| Owner: | changed from to |
|---|---|
| Status: | new → assigned |
| Triage Stage: | Unreviewed → Accepted |
comment:3 by , 11 years ago
| Component: | Uncategorized → Database layer (models, ORM) |
|---|---|
| Has patch: | set |
| Triage Stage: | Accepted → Ready for checkin |
Seems like a candidate for backport.
comment:4 by , 11 years ago
| Resolution: | → fixed |
|---|---|
| Status: | assigned → closed |
Note:
See TracTickets
for help on using tickets.
See: https://github.com/django/django/pull/4239
Funnily enough, being explicit worked before this patch:
CaseTestModel.objects.filter(integer__lte=2).annotate(test=Case( When(integer=1, then=2), When(integer=2, then=1), default=3, output_field=models.IntegerField(), )).order_by(F('test').asc())The problem is that the same instance of each
Whenclause has resolve_expression called on it multiple times. Once for the annotation, and once again for the order_by. The problem is that When.resolve_expression converts the Q() into a WhereNode(), and overwrites the condition property. It's not idempotent.