Opened 10 years ago
Closed 10 years ago
#25670 closed Bug (fixed)
`dictsort` does not work when `arg` parameter is numeric
| Reported by: | Andrew Kuchev | Owned by: | Andrew Kuchev |
|---|---|---|---|
| Component: | Template system | Version: | 1.8 |
| Severity: | Normal | Keywords: | template filter dictsort |
| Cc: | Triage Stage: | Accepted | |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
According to dictsort documentation, it orders given list of dictionaries, using arg as property in each dictionary:
@register.filter(is_safe=False)
def dictsort(value, arg):
"""
Takes a list of dicts, returns that list sorted by the property given in
the argument.
"""
try:
return sorted(value, key=Variable(arg).resolve)
except (TypeError, VariableDoesNotExist):
return ''
However, it is not possible to order list of dictionaries by a numeric key. Let's consider the following test case:
def test_sort_list_of_tuple_like_dicts(self):
data = [{'0': 'a', '1': '42'},
{'0': 'c', '1': 'string'},
{'0': 'b', '1': 'foo'}]
sorted_data = dictsort(data, '0')
self.assertEqual([{'0': 'a', '1': '42'},
{'0': 'b', '1': 'foo'},
{'0': 'c', '1': 'string'}], sorted_data)
This test fails with the following message:
Traceback (most recent call last):
File ".../django/tests/template_tests/filter_tests/test_dictsort.py", line 50, in test_sort_list_of_tuple_like_dicts
{'0': 'c', '1': 'string'}], sorted_data)
AssertionError: Lists differ: [{'0': 'a', '1': '42'}, {'0': 'b', '1': 'foo'}, {'0': 'c', '1': 'string'}] != [{'0': 'a', '1': '42'}, {'0': 'c', '1': 'string'}, {'0': 'b', '1': 'foo'}]
First differing element 1:
{'0': 'b', '1': 'foo'}
{'0': 'c', '1': 'string'}
- [{'0': 'a', '1': '42'}, {'0': 'b', '1': 'foo'}, {'0': 'c', '1': 'string'}]
+ [{'0': 'a', '1': '42'}, {'0': 'c', '1': 'string'}, {'0': 'b', '1': 'foo'}]
The dictsort uses sorted function with key=Variable(arg).resolve. When arg is '0', key function should behave like operator.itemgetter('0'), but Variable('0').resolve(context) returns 0 regardless of given context.
There are five usages of dictsort with "0" as arg in debug.py
As mentioned by bmispelon, this may be some kind of regression in Django 1.3.
Change History (8)
comment:1 by , 10 years ago
| Triage Stage: | Unreviewed → Accepted |
|---|
comment:2 by , 10 years ago
| Status: | new → assigned |
|---|
comment:4 by , 10 years ago
I'm not sure about this. It seems like the old behavior was somewhat accidental. Having a filter called "dictsort" work on a list of lists seems a bit odd and unintuitive. Maybe we should ask for other opinions on the django-developers mailing list. Maybe there is a common third-party filter that would do the job that we could add to builtins.
comment:5 by , 10 years ago
After some further thought, I changed my mind given the fact that dictsort doesn't work with numeric string keys. That's definitely a bug that should be fixed.
comment:6 by , 10 years ago
| Patch needs improvement: | set |
|---|
I left comments for improvement on the pull request.
comment:7 by , 10 years ago
| Patch needs improvement: | unset |
|---|
This ticket is a spinoff of #25646.