Opened 16 years ago
Closed 13 years ago
#9415 closed Uncategorized (wontfix)
QuerySet.order_by() should be chainable
Reported by: | Joey Wilhelm | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.0 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Design decision needed | |
Has patch: | yes | Needs documentation: | yes |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
I have a case where it would be very convenient to be able to call order_by() multiple times, appending to the order by clause with each successive call; i.e.,
foo = Model.objects.all().order_by('field1') if bar: foo = foo.order_by('-field2')
Currently, the second call to order_by() explicitly overrides the previous order. This is not the behavior I would expect, as most (all?) other methods on a QuerySet are chainable.
If it is decided that chaining will not be allowed with order_by(), then I think that this fact should at least be documented. Had I not been printing out my connection's queries when I ran into this problem, it may have taken me some time to figure out exactly what was going on.
Attachments (1)
Change History (11)
comment:1 by , 16 years ago
Triage Stage: | Unreviewed → Design decision needed |
---|
comment:2 by , 16 years ago
FWIW the code changes needed would be VERY minimal once a good API is determined.
by , 16 years ago
Attachment: | order-by-reset.diff added |
---|
patch that adds the proposed reset kwarg, backwards compatible
comment:3 by , 16 years ago
Has patch: | set |
---|---|
Needs documentation: | set |
comment:4 by , 16 years ago
Bikeshedding: Explicitly setting reset=False
seems weird (a default of True
is the odd bit, I guess).
How about if it was append=True
instead?
Agreed that if this ticket is wontfixed, the docs should at least be clarified.
comment:5 by , 16 years ago
SmileyChris: bikeshed all you want, I let people who know how to design APIs do that :)
comment:6 by , 16 years ago
To get around this until the patch lands, we currently have an ordering = [] set and as the orderings are picked up append to ordering. The final step is then qset = qset.order_by(*ordering).
comment:7 by , 16 years ago
Resolution: | → wontfix |
---|---|
Status: | new → closed |
No, the current behaviour is deliberate. The reason is that chaining for ordering would actually behave very counter-intuitively, since ordering is left-to-right sensitive in terms of "most significant" to "least significant". Things added after the initial ordering end up having almost no effect on the result, because the leading ordering terms dominate.
I don't see it as really common enough that the major ordering is going to be added in one place and minor tweaking of the far right, inisignificant terms will happen later that it's worth complicating the UI here.
A docs patch would be fine (in another ticket so that we can review it in isolation), but the current behaviour is quite intentional and it would be counter-productive to change it.
comment:8 by , 13 years ago
Easy pickings: | unset |
---|---|
Resolution: | wontfix |
Severity: | → Normal |
Status: | closed → reopened |
Type: | → Uncategorized |
UI/UX: | unset |
I'd run into the same problem without an easy solution ...I pass around a lazy orderset in a structure hierarchy of classes and the possibility of adding an order_by secondary clauses for different cases.
@mtredinnick: I understand you may not have use cases where you can see the value in this, however providing an append=True option will neither bloat the code nor have a performance impact.
comment:9 by , 13 years ago
Easy pickings: | set |
---|
Just to clarify futher:
Currently this works (and secondary order is very significant when you have lots of items matching on the first order key)
foo = Model.objects.all().order_by('field1', 'field2')
all that is being proposed is a fully backward compatible minor enhancement with no negative impact whatsoevery:
foo = Model.objects.all().order_by('field1')
.......
.......
if bar:
foo = foo.order_by('field2', append=True) # For use cases where the original order_by is not known...this again has no harm, and for people who don't need it don't need to use it!!
comment:10 by , 13 years ago
Easy pickings: | unset |
---|---|
Resolution: | → wontfix |
Status: | reopened → closed |
Please don't reopen a ticket closed by a core developer.
If you want to reverse a decision made by a core developer, you should write to the django-developers mailing-list.
Take a look at the contribution guidelines in the docs for more information. Thanks :)
having them just chainable by default would be backwards incompatible, so it really can't be done, however perhaps their could be a kwarg to tell order_by not to remove the previous ordering(reset=False perhaps?).