Can I make Django QueryDict preserve ordering?

大城市里の小女人 提交于 2019-12-09 17:06:49

问题


Is it possible to to make Django's QueryDict preserve the ordering from the original query string?

>>> from django.http import QueryDict
>>> q = QueryDict(u'x=foo³&y=bar(potato),z=hello world')
>>> q.urlencode(safe='()')
u'y=bar(potato)%2Cz%3Dhello%20world&x=foo%C2%B3'

回答1:


QueryDict inherits from Django's MultiValueDict which inherits from dict which is implemented as a hash table. Thus, you can't guarantee it will stay ordered.

I'm not sure if this will be relevant to what you need, but an ordering that QueryDict does preserve is the order of "lists" (multiple values for the same key) passed in to them. Using this, you could do:

>>> from django.http import QueryDict
>>> q = QueryDict(u'x=foo³&x=bar(potato),x=hello world')
>>> q.lists()
[('x', ['foo³', 'bar(potato)', 'hello world'])]
>>> q.urlencode(safe='()')
u'x=foo%C2%B3&x=bar(potato)&x=hello%20world'



回答2:


QueryDict class is based on MultiValueDict class that is based on regular python dict, which is an unordered collection as you know.

According to the source code, QueryDict internally uses urlparse.parse_qsl() method, which preserves the order of query parameters, outputs a list of tuples:

>>> from urlparse import parse_qsl
>>> parse_qsl('x=foo³&y=bar(potato),z=hello world')
[('x', 'foo\xc2\xb3'), ('y', 'bar(potato),z=hello world')]

What you can do, is to use the order of keys given by the parse_qsl() for sorting:

>>> order = [key for key, _ in parse_qsl('x=foo³&y=bar(potato),z=hello world')]
>>> order
['x', 'y']

Then, subclass QueryDict and override lists() method used in urlencode():

>>> class MyQueryDict(QueryDict):
...     def __init__(self, query_string, mutable=False, encoding=None, order=None):
...         super(MyQueryDict, self).__init__(query_string, mutable=False, encoding=None)
...         self.order = order
...     def lists(self):
...         return [(key, self.getlist(key)) for key in self.order]
... 
>>> q = MyQueryDict(u'x=foo³&y=bar(potato),z=hello world', order=order)
>>> q.urlencode(safe='()')
u'x=foo%C2%B3&y=bar(potato)%2Cz%3Dhello%20world'

The approach is a bit ugly and may need further improvement, but hope at least it'll give you an idea of what is happening and what you can do about it.



来源:https://stackoverflow.com/questions/23662247/can-i-make-django-querydict-preserve-ordering

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!