我可以让Django QueryDict保持排序吗?

wim*_*wim 8 python django http query-string

是否有可能使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'
Run Code Online (Sandbox Code Playgroud)

ale*_*cxe 2

QueryDictclass 基于MultiValueDict基于常规 python 的类dict,如您所知,这是一个无序集合。

\n\n

根据源码QueryDict内部使用urlparse.parse_qsl()方法,保留查询参数的顺序,输出一个元组列表:

\n\n
>>> from urlparse import parse_qsl\n>>> parse_qsl(\'x=foo\xc2\xb3&y=bar(potato),z=hello world\')\n[(\'x\', \'foo\\xc2\\xb3\'), (\'y\', \'bar(potato),z=hello world\')]\n
Run Code Online (Sandbox Code Playgroud)\n\n

您可以做的是使用 for 排序给出的键顺序parse_qsl()

\n\n
>>> order = [key for key, _ in parse_qsl(\'x=foo\xc2\xb3&y=bar(potato),z=hello world\')]\n>>> order\n[\'x\', \'y\']\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后,子类QueryDict和重写lists()方法中使用urlencode()

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

该方法有点丑陋,可能需要进一步改进,但希望至少它能让您了解正在发生的事情以及您可以采取哪些措施。

\n