Можно ли упорядочить заказ Django QueryDict?

Возможно ли сделать QueryDict Django сохранением заказа из исходной строки запроса?

>>> 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' 

3 Solutions collect form web for “Можно ли упорядочить заказ Django QueryDict?”

QueryDict наследует от QueryDict от Django, который наследует от dict который реализован как хеш-таблица . Таким образом, вы не можете гарантировать, что он будет оставаться заказанным.

Я не уверен, что это будет иметь отношение к тому, что вам нужно, но заказ, который QueryDict сохраняет, – это порядок «списков» (несколько значений для одного и того же ключа), переданных им . Используя это, вы можете сделать:

 >>> 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' 

Класс QueryDict основан на классе MultiValueDict который основан на регулярном python dict , который является неупорядоченной коллекцией, как вы знаете.

Согласно исходному коду 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 и метод override 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[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' 

Этот подход немного уродлив и может нуждаться в дальнейшем улучшении, но, надеюсь, по крайней мере, он даст вам представление о том, что происходит и что вы можете с этим поделать.

Возвращаясь к этому вопросу почти через 3 года, я понял, что мы можем тривиально сделать QueryDict который сохраняет упорядочение по зависимостям, впрыскивая collections.OrderedDict как бэкенд отображения:

 >>> class MyQueryDict(QueryDict, OrderedDict): ... pass ... >>> QueryDict(u'x=1&y=2&z=3').urlencode() u'y=2&x=1&z=3' >>> MyQueryDict(u'x=1&y=2&z=3').urlencode() u'x=1&y=2&z=3' 

Он работает, потому что super делегаты в соответствии с MRO , поэтому MyQueryDict должен прокси-серверу для OrderedDict для хранения вместо использования обычного Python dict .

 >>> QueryDict.__mro__ (django.http.request.QueryDict, django.utils.datastructures.MultiValueDict, dict, object) >>> MyQueryDict.__mro__ (__main__.MyQueryDict, django.http.request.QueryDict, django.utils.datastructures.MultiValueDict, collections.OrderedDict, # <-- new kid on the block! dict, object) 
Interesting Posts

webbrowser.get («firefox») на Mac с Firefox «не смог найти исполняемый браузер»

Python: итерация над столбцом фрейма данных, проверка значения условия, хранящегося в массиве, и получение значений в списке

Существует ли Perl эквивалент Python `if __name__ == '__main __'`?

Повесьте скрипт Python с помощью SQLAlchemy и многопроцессорности

Двунаправленный дистрибутив CDF / CCDF Python

Pandas разделяет имя столбца на имя и фамилию, если содержит одно пространство

Индикатор выполнения во время операций pandas (python)

Ножницы для рок-бумаги – Python 3 – новичок

python: имя модуля, имеющего имя из двух слов

Как построить данные с Python из текстового файла

объединение двух кадров данных по столбцу и индексу

Заполнение одного цветного фона в OpenCV

Пул многопроцессорности Python внутри процесса демона

Как остановить BaseHTTPServer.serve_forever () в подклассе BaseHTTPRequestHandler?

Плотные настройки SIFT для OpenCV-Python

Python - лучший язык программирования в мире.