Come cambiare un django QueryDict in Python Dict?


111

Facciamo finta di avere il seguente QueryDict:

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

Mi piacerebbe avere un dizionario fuori da questo, ad esempio:

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

(Non mi interessa se il simbolo Unicode urimane o scompare.)

Se lo faccio queryDict.dict(), come suggerito dal sito django , perdo i valori extra appartenenti a var1, es:

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

Stavo pensando di fare questo:

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

C'è un modo migliore?

Risposte:


103

Questo dovrebbe funzionare: myDict = dict(queryDict.iterlists())


4
queryDict.iterlists () sta creando un valore di lista da ogni chiave, forse perché tu visualizzi le liste ?, queryDict.iteritems () se sai che querydict non contiene la lista.
panchicore

3
In django 1.6: dict (data._iteritems ())
Bas Koopmans,

5
In Django 1.6, dict(queryDict.lists())sembra funzionare
Dan Passaro

39
In Django 1.8 su Python 3 tutto ciò di cui avevo bisogno era dict(queryDict).
fmalina

1
Questo non funziona per molte librerie, inclusa la funzione automatica. Vedi la mia domanda e la mia risposta qui (funziona con v2 e v3 di python): stackoverflow.com/questions/37026535/…
Olivier Pons

193

Due modi per scoprirlo, provarlo o visualizzare la fonte. La risposta è no: def dict (self): "" "Restituisce l'oggetto corrente come un dict con valori singolari." "" Return dict ((key, self [key]) per chiave in self)
dalore

6
Sebbene questo risolva il problema per alcune delle persone che accedono a questa pagina da Google, non risponde alla domanda di OP che chiede esplicitamente di conservare più valori per una chiave.
rivolta il

1
Grazie a Dio per questa risposta. Ero così
incapace

Lavorando su Django 1.11
jobima

16

Questo è quello che ho finito per usare:

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

Dal mio utilizzo questo sembra darti un elenco che puoi inviare ad esempio a un costruttore di form.

EDIT: forse questo non è il metodo migliore. Sembra che se si desidera, ad esempio, scrivere QueryDictsu un file per qualsiasi motivo folle, QueryDict.urlencode()è la strada da percorrere. Per ricostruire il QueryDictfai semplicemente QueryDict(urlencoded_data).


3
Questo metodo soffre di comportamento indeterminato; in una situazione in cui una determinata chiave può avere uno o più valori, a volte potresti ottenere una stringa e talvolta un elenco di stringhe.
Asherah

8
from django.utils import six 
post_dict = dict(six.iterlists(request.POST))

6

Se non vuoi i valori come array puoi fare quanto segue:

# 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 è un potente strumento per saperne di più qui http://docs.python.org/2/library/functions.html#zip


2
So che ha quasi 6 anni, sto solo indicando a chi arriva questa risposta: In Django> = 2.0 (potrebbe funzionare anche nelle versioni precedenti, è proprio quello che sto usando), puoi fare QueryDict.dict()(cioè request.POST.dict()) e restituirà i valori correttamente.
Luca Bezerra

Luca sei una leggenda. Questo mi ha fatto impazzire tutto il giorno! La tua è l'unica risposta che riesco a trovare al lavoro.
scottapotamus

4

Mi sono imbattuto in un problema simile, volendo salvare valori arbitrari da un modulo come valori serializzati.

La mia risposta evita di iterare esplicitamente il contenuto del dizionario: dict(querydict.iterlists())

Per recuperare un valore simile a un dizionario che funzioni come l'originale, una funzione inversa utilizza QueryDict.setlist()per popolare un nuovo QueryDictvalore. In questo caso, non credo che l'iterazione esplicita sia evitabile.

Le mie funzioni di supporto hanno questo aspetto:

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

Aggiornare:

myDict = dict(queryDict._iterlists())

Nota: il carattere di sottolineatura _nel metodo degli elenchi di queryDict. Versione Django: 1.5.1


3

dict(request.POST) restituisce uno strano dizionario Python con valori avvolti da array.

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

dove as {x:request.POST.get(x) for x in request.POST.keys()}restituisce l'output atteso.

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

In Django> = 2.0 (potrebbe funzionare anche nelle versioni precedenti, è solo quella che sto usando), puoi fare QueryDict.dict()(cioè request.POST.dict()) e restituirà i valori correttamente.
Luca Bezerra

2

basta semplicemente aggiungere

queryDict=dict(request.GET) o queryDict=dict(QueryDict)

Nella tua visualizzazione i dati verranno salvati in querDict come python Dict.


1

Ecco come ho risolto il problema:

dict_ = {k: q.getlist(k) if len(q.getlist(k))>1 else v for k, v in q.items()}

1

Come me, probabilmente hai più familiarità con i Dict()metodi in Python. Tuttavia, QueryDict()è anche un oggetto facile da usare. Ad esempio, forse volevi ottenere il valore da request.GET QueryDict().

È possibile farlo in questo modo: request.GET.__getitem__(<key>).

QueryDict()documentazione: https://docs.djangoproject.com/en/2.0/ref/request-response/#django.http.QueryDict


1
Evita di usare i metodi del doppio trattino basso. Il modo più pitonico sarebbe usare request.GET.get(<key>)orequest.GET.getlist(<key>)
Bobort

1

Con Django 2.2ci sono poche soluzioni pulite:

  1. QueryDict.dict()è più semplice ma si romperà QueryDictcon gli elenchi come valori, ad esempio:
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)

verrà prodotto

a two  # <--- missed 'one'
b three
  1. dict(QueryDict) è migliore perché renderà il dizionario corretto degli elenchi:
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)

verrà prodotto

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

che è corretto.


0

Ho provato sia dict(request.POST)e request.POST.dict()e mi sono reso conto che se hai listvalori ad esempio 'var1':['value1', 'value2']nidificati nel tuo request.POST, il later ( request.POST.dict()) mi dava accesso solo all'ultimo elemento in un elenco nidificato mentre il primo ( dict(request.POST)) mi consentiva di accedere a tutti gli elementi in un elenco nidificato.

Spero che questo aiuti qualcuno.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.