是否可以让Django的QueryDict保留原始查询字符串的排序?
>>> 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'
答案 0 :(得分:2)
QueryDict
继承自Django的MultiValueDict
,继承自dict
implemented as a hash table。因此,您不能保证它会保持订购。
我不确定这是否与您的需求相关,但an ordering that QueryDict does preserve is the order of "lists" (multiple values for the same key) passed in to them。使用它,你可以这样做:
>>> 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'
答案 1 :(得分:1)
QueryDict
类基于MultiValueDict
类,该类基于常规python dict
,如您所知,这是一个无序集合。
根据source code,QueryDict
内部使用urlparse.parse_qsl()
方法,该方法保留查询参数的顺序,输出元组列表:
>>> 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')]
您可以做的是使用parse_qsl()
给出的键的顺序进行排序:
>>> order = [key for key, _ in parse_qsl('x=foo³&y=bar(potato),z=hello world')]
>>> order
['x', 'y']
然后,子类QueryDict
并覆盖lists()
中使用的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'
这种方法有点难看,可能需要进一步改进,但希望至少它会让你了解正在发生的事情以及你可以采取的措施。