#19195 closed Bug (fixed)
Using distinct([*fields]) filter on a foreign key produces an ordering error when the foreign key has a Meta ordering field.
Reported by: | Owned by: | nobody | |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.7-beta-2 |
Severity: | Release blocker | Keywords: | distinct, query |
Cc: | Simon Charette | 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 (last modified by )
I tried to using a distinct filter like this: Appearance.objects.order_by('team').distinct('team'); this fails with the following Database Error: "DatabaseError: SELECT DISTINCT ON expressions must match initial ORDER BY expressions"
It is possible to work around this problem by using this modified filter: Appearance.objects.order_by('team__id').distinct('team__id')
.
Model definition: http://pastebin.com/index/J45fy9fr
Full traceback: http://pastebin.com/feSFMbzX
Change History (16)
comment:1 by , 12 years ago
Triage Stage: | Unreviewed → Accepted |
---|
comment:2 by , 12 years ago
There should actually be two underscores for the team_id filter - order_by fails on team_id.
comment:3 by , 12 years ago
I think we should allow using .order_by('team_id') here.
Related fields have two attributes on model level - team and team_id in this case. We allow using team_id in many places in the ORM already, and to me it seems we should allow it in order_by and distinct, too.
Is there some reason to *not* allow them?
comment:6 by , 11 years ago
Cc: | added |
---|---|
Description: | modified (diff) |
Just hit this issue and had a hard time figuring out what I've done wrong.
Intuitively I tried .distinct('related_id').order_by('related_id')
after realizing removing my Related._meta.ordering
solved the issue but, as pointed out by akaariai, this is not allowed ATM.
Replying to akaariai:
I think we should allow using .order_by('team_id') here.
Related fields have two attributes on model level - team and team_id in this case. We allow using team_id in many places in the ORM already, and to me it seems we should allow it in order_by and distinct, too.
Is there some reason to *not* allow them?
I can't think of any reason we'd like *not* to allow them. It looks like sanest to expose an API to explicitly opt-out of the existing related model ordering behavior while maintaining backward compatibility.
comment:7 by , 11 years ago
Calling order_by('team_id')
doesn't raise a FieldError
anymore on Django 1.7 and silently behave just like order_by('team')
.
If we want to avoid breaking code that might rely on this in 1.7 we should fix it now. Else we'll have to deal with this by introducing an entry point to order_by
in order to opt-out of this unexpected behavior.
I wrote a patch for the order_by issue here.
comment:8 by , 11 years ago
Yes, I think we should do this for 1.7. Some review comments:
- The actual code changes look correct
- Release notes and some documentation changes for order_by() needed
The test changes looked a bit scary to me (do all existing tests continue to test what they originally tested?), but after a bit more reading I think they are safe. A final check here wouldn't hurt.
comment:9 by , 11 years ago
Severity: | Normal → Release blocker |
---|---|
Version: | 1.4 → 1.7-beta-2 |
Setting release blocker flag per previous comment.
comment:10 by , 11 years ago
Has patch: | set |
---|
Create a PR with doc and release note. I would appreciate a wording review.
In order to make sure the test refactoring didn't break anything I review and moved every cases in their own methods. I you feel like this is adding too much noise to the patch I can remove this part from the final patch.
comment:11 by , 11 years ago
Triage Stage: | Accepted → Ready for checkin |
---|
Left some comments for doc improvements.
comment:12 by , 11 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
comment:14 by , 11 years ago
I've found an issue with Django 1.7 checks framework and this ticket.
Now we're allowed to order by fieldname
as before and by fieldname_id
(without joins).
But django/db/models/base.py _check_ordering
method still does not allow to set fieldname_id
as one of Meta.ordering values.
I've made a patch here: https://github.com/Vincent-Vega/django/commit/7d94a3d822746f2815e7184928311e1d91dff467
I'm quite new to contributing (and also django faq says that pull requests without ticket are not accepted on github).
So it would be nice if you explain what can I do next.
comment:15 by , 11 years ago
Hi Althalus, you should open a ticket for this and refer to it from your pull request. This looks like a legitimate bug.
The problem is that .distinct('team') can't do distinct on Team._meta.ordering as that will give unexpected results if the Team._meta.ordering isn't unique. In general, the user doesn't want that anyways. On the other hand we can't alter what .order_by('team') does. So, I think we have to disallow doing .distinct('team') if there is ordering defined for the related model.
The error should point to using .distinct('team_id').order_by('team_id') - though this syntax doesn't seem to work at the moment.