Як змінити 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']}

(Мені байдуже, чи символ Unicode 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 (), якщо вам відомо, що запит не містить списку.
panchicore

3
In 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 пітона): stackoverflow.com/questions/37026535/…
Олів'є Понс

193

Два способи дізнатися, спробувати його або переглянути джерело. Відповідь - ні: def dict (self): "" "Повертає поточний об'єкт як дикт із сингулярними значеннями." "" Return dict ((ключ, self [key]) для ключа у self)
dalore

6
Хоча це і вирішує проблему для деяких людей, які приходять на цю сторінку з google, це не відповідає на питання ОП, яке явно просить зберегти кілька значень для ключа.
бунтував

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()}

З мого використання, схоже, ви отримаєте список, який ви можете повернути, наприклад, конструктору форм.

EDIT: можливо, це не найкращий метод. Здається, якщо ви хочете, наприклад, написати QueryDictв файл з будь-якої божевільної причини, QueryDict.urlencode()це шлях. Для реконструкції QueryDictви просто робите QueryDict(urlencoded_data).


3
Цей метод страждає від невизначеної поведінки; в ситуації, коли даний ключ може мати одне або більше значень, іноді ви можете отримати рядок, а іноді отримати список рядків.
Ашера


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())

Будь ласка, зауважте: підкреслити _в ітеральних списках метод queryDict. Версія Джанго: 1.5.1


3

dict(request.POST) повертає дивний словник python із значеннями, оберненими масивом.

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

де як {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()}

1

Як і я, напевно, ви більше знайомі з Dict()методами в пітоні. Однак, 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, пізніше ( request.POST.dict()) надав мені доступ до останнього елемента в вкладеному списку, тоді як колишній ( dict(request.POST)) дозволив мені отримати доступ до всіх елементів у вкладеному списку.

Я сподіваюся, що це комусь допоможе.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.