Как изменить django QueryDict на Python Dict?

111

Представим, что у меня есть следующий QueryDict:

<QueryDict: {u'num': [0], u'var1': [u'value1', u'value2'], u'var2': [u'8']}>

Я бы хотел взять из этого словарь, например:

{'num': [0], 'var1':['value1', 'value2'], 'var2':['8']}

(Меня не волнует, uостанется ли символ Юникода или нет.)

Если я это сделаю queryDict.dict(), как это предлагает сайт django , я потеряю дополнительные значения var1, например:

{'num': [0], 'var1':['value2'], 'var2':['8']}

Я думал об этом:

myDict = {}
for key in queryDict.iterkeys():
    myDict[key] = queryDict.getlist(key)

Есть ли способ лучше?

СайянДевочка
источник

Ответы:

103

Это должно работать: myDict = dict(queryDict.iterlists())

Александр Вассалотти
источник
4
queryDict.iterlists () создает значение списка из каждого ключа, возможно, потому что вы просматриваете списки ?, queryDict.iteritems (), если вы знаете, что querydict не содержит списка.
panchicore 07
3
В django 1.6: dict (data._iteritems ())
Bas Koopmans
5
В Django 1.6 dict(queryDict.lists())вроде работает
Дэн Пассаро
39
В Django 1.8 на Python 3 все, что мне было нужно, это dict(queryDict).
fmalina
1
Это не работает для многих библиотек, включая автоматические. Смотрите мой вопрос и мой собственный ответ здесь (работает с v2 и v3 Python): stackoverflow.com/questions/37026535/…
Оливье Понс,
195

Новое в Django> = 1.4.

QueryDict.dict()

https://docs.djangoproject.com/en/stable/ref/request-response/#django.http.QueryDict.dict

панчикор
источник
Два способа узнать, попробовать или просмотреть источник. Ответ - нет: def dict (self): "" "Возвращает текущий объект как dict с единственными значениями." "" Return dict ((key, self [key]) для ключа в self)
dalore
6
Хотя это решает проблему для некоторых людей, которые переходят на эту страницу из Google, он не отвечает на вопрос OP, который явно просит сохранить несколько значений для ключа.
бунтовал
1
Слава богу за этот ответ. Я был таким невежественным
Ник Ванавит
Работа над Django 1.11
jobima
16

Вот что я в итоге использовал:

def qdict_to_dict(qdict):
    """Convert a Django QueryDict to a Python dict.

    Single-value fields are put in directly, and for multi-value fields, a list
    of all values is stored at the field's key.

    """
    return {k: v[0] if len(v) == 1 else v for k, v in qdict.lists()}

По моему мнению, это дает вам список, который вы можете отправить обратно, например, в конструктор формы.

РЕДАКТИРОВАТЬ: возможно, это не лучший метод. Кажется, если вы хотите, например, записать QueryDictв файл по какой-то безумной причине, QueryDict.urlencode()это правильный путь. Чтобы восстановить то, что QueryDictвы просто делаете QueryDict(urlencoded_data).

Дэн Пассаро
источник
3
Этот метод страдает неопределенным поведением; в ситуации, когда данный ключ может иметь одно или несколько значений, вы можете иногда получить строку, а иногда получить список строк.
Asherah
8
from django.utils import six 
post_dict = dict(six.iterlists(request.POST))
ytyng
источник
6

Если вам не нужны значения в виде массивов, вы можете сделать следующее:

# request = <QueryDict: {u'key': [u'123ABC']}>
dict(zip(request.GET.keys(), request.GET.values()))
{u'key': u"123ABC" }

# Only work for single item lists
# request = <QueryDict: {u'key': [u'123ABC',U 'CDEF']}>
dict(zip(request.GET.keys(), request.GET.values()))
{u'key': u"CDEF" } 

zip - мощный инструмент, подробнее об этом читайте здесь http://docs.python.org/2/library/functions.html#zip

Кричард
источник
2
Я знаю, что ему почти 6 лет, просто указываю для тех, кто дойдет до этого ответа: в Django> = 2.0 (может работать и в более старых версиях, это только тот, который я использую), вы можете сделать QueryDict.dict()(т.е. request.POST.dict()) и это вернет значения правильно.
Лука Безерра
Лука, ты легенда. Это сводило меня с ума весь день! Ваш единственный ответ, который я могу приступить к работе.
scottapotamus
4

Я столкнулся с аналогичной проблемой, желая сохранить произвольные значения из формы как сериализованные значения.

В моем ответе я избегаю явного повторения содержимого словаря: dict(querydict.iterlists())

Чтобы получить словарное значение, которое функционирует как исходное, обратная функция использует QueryDict.setlist()для заполнения нового QueryDictзначения. В этом случае я не думаю, что явной итерации можно избежать.

Мои вспомогательные функции выглядят так:

from django.http import QueryDict

def querydict_dict(querydict):
    """
    Converts a Django QueryDict value to a regular dictionary, preserving multiple items.
    """
    return dict(querydict.iterlists())

def dict_querydict(dict_):
    """
    Converts a value created by querydict_dict back into a Django QueryDict value.
    """
    q = QueryDict("", mutable=True)
    for k, v in dict_.iteritems():
        q.setlist(k, v)
    q._mutable = False
    return q
Грэм Клайн
источник
3

Обновить:

myDict = dict(queryDict._iterlists())

Обратите внимание: подчеркивание _в методе iterlists queryDict. Версия Django: 1.5.1

Парфыз
источник
3

dict(request.POST) возвращает странный словарь Python со значениями, заключенными в массив.

{'start': ['2017-01-14T21:00'], 'stop': ['2017-01-14T22:00'], 'email': ['sandeep@sakethtech.com']}

где as {x:request.POST.get(x) for x in request.POST.keys()}возвращает ожидаемый результат.

{'start': '2017-01-14T21:00', 'stop': '2017-01-14T22:00', 'email': 'sandeep@sakethtech.com'}
Сандип
источник
В Django> = 2.0 (может работать и в более старых версиях, это как раз тот, который я использую) вы можете сделать QueryDict.dict()(т.е. request.POST.dict()), и он вернет значения правильно.
Лука Безерра
2

просто добавьте

queryDict=dict(request.GET) или queryDict=dict(QueryDict)

По вашему мнению, данные будут сохранены в querDict как python Dict.

Омкар Ядав
источник
1

Вот как я решил эту проблему:

dict_ = {k: q.getlist(k) if len(q.getlist(k))>1 else v for k, v in q.items()}
mbijou
источник
1

Как и я, вы, вероятно, больше знакомы с Dict()методами в Python. Однако QueryDict()это также простой объект в использовании. Например, возможно, вы хотели получить значение из request.GET QueryDict().

Вы можете сделать это следующим образом: request.GET.__getitem__(<key>).

QueryDict()документация: https://docs.djangoproject.com/en/2.0/ref/request-response/#django.http.QueryDict

Маркистадор
источник
1
Избегайте использования методов двойного подчеркивания. Более питоническим способом было бы использовать request.GET.get(<key>)илиrequest.GET.getlist(<key>)
Боборт
1

С Django 2.2Есть несколько чистых решений:

  1. QueryDict.dict()самый простой, но он сломается QueryDictсо списками в качестве значений, например:
from django.http.request import QueryDict, MultiValueDict

query_dict = QueryDict('', mutable=True)
query_dict.update(MultiValueDict({'a': ['one', 'two']}))
query_dict.update({'b': 'three'})

for key, value in query_dict.dict().items():  # ---> query_dict.dict()
    print(key, value)

выведет

a two  # <--- missed 'one'
b three
  1. dict(QueryDict) лучше, потому что он сделает правильный словарь списков:
from django.http.request import QueryDict, MultiValueDict

query_dict = QueryDict('', mutable=True)
query_dict.update(MultiValueDict({'a': ['one', 'two']}))
query_dict.update({'b': 'three'})

for key, value in dict(query_dict).items():  # ---> dict(query_dict)
    print(key, value)

выведет

a ['one', 'two']
b ['three']

что правильно.

валекс
источник
0

Я опробовал оба dict(request.POST)и request.POST.dict()и понял, что если у вас есть listзначения, например, 'var1':['value1', 'value2']вложенные в ваш request.POST, later ( request.POST.dict()) предоставил мне доступ только к последнему элементу во вложенном списке, а первый ( dict(request.POST)) позволил мне получить доступ ко всем элементам во вложенном списке.

Я надеюсь, что это поможет кому-то.

Codebender
источник