TLDR: повторно внедрить lists
:
class OrderedQueryDict(QueryDict, OrderedDict):
def lists(self):
"""Returns a list of (key, list) pairs."""
return [(key, self.getlist(key)) for key in self]
Для полной функциональности, iterlists
также необходимо повторно реализовать.
Проблема в том, что MultiValueDict
в Django перезаписывает __getitem__
для получения только последнего значения, а getlist
для получения всех значений. Это неявно опирается на другие методы базового отображения, не использующие переопределенные методы. Например, он опирается на super().iteritems
возможность извлекать списки значений:
>>> from django.utils.datastructures import MultiValueDict
>>> d = MultiValueDict({"k": ["v1", "v2"]})
>>> d.items()
[('k', 'v2')]
>>> super(MultiValueDict, d).items()
[('k', ['v1', 'v2'])]
Исходный код использует six
для охвата Python 2 и 3. Вот что выполняет Python 2:
def lists(self):
return list(self.iterlists())
def iterlists(self):
"""Yields (key, list) pairs."""
return super(MultiValueDict, self).iteritems()
В Python 2 OrderedDict
реализован в чистом Python и использует self[key]
, т.е. __getitem__
, для получения значений:
def iteritems(self):
'od.iteritems -> an iterator over the (key, value) pairs in od'
for k in self:
yield (k, self[k])
Таким образом, он получает переопределенный __getitem__
из MRO и возвращает только отдельные значения, а не все списки.
Эта проблема обходит стороной в большинстве сборок Python 3.5+, поскольку OrderedDict
обычно имеет доступную C-реализацию, случайно отгораживая свои методы от использования переопределенных.
collection.OrderedDict теперь реализован в C, что делает его в 4-100 раз быстрее. [Что нового в Python 3.5]