144

Let's pretend I have the following QueryDict:

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

I'd like to have a dictionary out of this, eg:

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

(I don't care if the unicode symbol u stays or goes.)

If I do queryDict.dict(), as suggested by the django site, I lose the extra values belonging to var1, eg:

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

I was thinking of doing this:

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

Is there a better way?

SaiyanGirl
  • 16,376
  • 11
  • 41
  • 57

15 Answers15

246

New in Django >= 1.4.

QueryDict.dict()

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

IanS
  • 15,771
  • 9
  • 60
  • 84
panchicore
  • 11,451
  • 12
  • 74
  • 100
  • Two ways to find out, try it, or view the source. The answer is no: def dict(self): """ Returns current object as a dict with singular values. """ return dict((key, self[key]) for key in self) – dalore Nov 15 '13 at 10:31
  • 17
    While this solves the problem for some of the people who come to this page from google, it doesn't answer OP's question which explicitly asks for retaining multiple values for a key. – rioted Sep 30 '18 at 20:08
  • 1
    Thank god for this answer. I was so clueless – Nic Wanavit May 30 '19 at 20:15
  • Working on Django 1.11 – jobima Jun 26 '19 at 07:30
  • To keep all the elements a key can contains, it could be better to use `QueryDict.list()` https://docs.djangoproject.com/fr/4.0/ref/request-response/#django.http.QueryDict.lists that keeps all the elements. Then, we can cast the list of tuples obtained into a dictionary. – Teazane Jul 20 '22 at 10:13
118

This should work: myDict = dict(queryDict.iterlists())

Alexandre Vassalotti
  • 1,895
  • 2
  • 15
  • 14
16

This is what I've ended up using:

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

From my usage this seems to get you a list you can send back to e.g. a form constructor.

EDIT: maybe this isn't the best method. It seems if you want to e.g. write QueryDict to a file for whatever crazy reason, QueryDict.urlencode() is the way to go. To reconstruct the QueryDict you simply do QueryDict(urlencoded_data).

Dan Passaro
  • 4,211
  • 2
  • 29
  • 33
  • 3
    This method suffers from indeterminate behaviour; in a situation where a given key may have one or more values, you could sometimes get a string, and sometimes get a list of strings. – Asherah Jan 04 '16 at 03:11
11

just simply add

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

In your view and data will be saved in querDict as python Dict.

omkar yadav
  • 177
  • 5
  • 15
7

If you do not want the values as Arrays you can do the following:

# 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 is a powerful tool read more about it here http://docs.python.org/2/library/functions.html#zip

krichard
  • 3,699
  • 24
  • 34
  • 3
    I know this is almost 6 years old, just pointing out for whoever reaches this answer: In Django >= 2.0 (might work in older versions as well, that's just the one I'm using), you can do `QueryDict.dict()` (i.e. `request.POST.dict()`) and it will return the values properly. – Luca Bezerra Jan 10 '19 at 20:33
  • Luca you are a legend. This has been driving me mad all day! Yours is the only answer I can get to work. – scottapotamus Mar 03 '20 at 01:08
  • Luca, this is a great answer! Works great in django 3.1. I was building this dictionary the hard way, appending keys/values but this does in one line. – Milo Persic Aug 25 '20 at 13:56
  • Note: this does NOT work for multiple values (such as you'd get from a MultiSelectField). If your QueryDict has a key/value pair like this: ``, then the `.dict()` method will return `{'names': 'Jean'}` instead of `{'names': ['Joe', 'Matt', 'Jean']}` – ezeYaniv Jan 30 '23 at 22:59
7
from django.utils import six 
post_dict = dict(six.iterlists(request.POST))
ytyng
  • 575
  • 6
  • 8
4

I ran into a similar problem, wanting to save arbitrary values from a form as serialized values.

My answer avoids explicitly iterating the dictionary contents: dict(querydict.iterlists())

In order to retrieve a dictionary-like value that functions as the original, an inverse function uses QueryDict.setlist() to populate a new QueryDict value. In this case, I don't think the explicit iteration is avoidable.

My helper functions look like this:

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
Graham Klyne
  • 816
  • 10
  • 16
4

With Django 2.2 there are few clean solutions:

  1. QueryDict.dict() is simplest but it will break QueryDict with lists as values, e.g:
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)

will output

a two  # <--- missed 'one'
b three
  1. dict(QueryDict) is better because it will make correct dictionary of lists:
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)

will output

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

which is correct.

Federico Gentile
  • 5,650
  • 10
  • 47
  • 102
valex
  • 5,163
  • 2
  • 33
  • 40
3

Update:

myDict = dict(queryDict._iterlists())

Please Note : underscore _ in iterlists method of queryDict. Django version :1.5.1

SaiyanGirl
  • 16,376
  • 11
  • 41
  • 57
Parthyz
  • 161
  • 2
  • 4
3

dict(request.POST) returns a weird python dictionary with array wrapped values.

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

where as {x:request.POST.get(x) for x in request.POST.keys()} returns expected output.

{'start': '2017-01-14T21:00', 'stop': '2017-01-14T22:00', 'email': 'sandeep@sakethtech.com'}
Sandeep
  • 28,307
  • 3
  • 32
  • 24
  • In Django >= 2.0 (might work in older versions as well, that's just the one I'm using), you can do `QueryDict.dict()` (i.e. `request.POST.dict()`) and it will return the values properly. – Luca Bezerra Jan 10 '19 at 20:32
2

This is how I solved that problem:

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

I tried out both dict(request.POST) and request.POST.dict() and realised that if you have list values for example 'var1':['value1', 'value2'] nested in your request.POST, the later(request.POST.dict()) only gave me access to the last item in a nested list while the former(dict(request.POST)) allowed me to access all items in a nested list.

I hope this helps someone.

Codebender
  • 195
  • 1
  • 10
1

Like me, you probably are more familiar with Dict() methods in python. However, the QueryDict() is also an easy object to use. For example, perhaps you wanted to get the value from the request.GET QueryDict().

You can do this like so: request.GET.__getitem__(<key>).

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

Marquistador
  • 1,841
  • 19
  • 26
  • 1
    Avoid using the double-underscore methods. The more pythonic way would be to use `request.GET.get()` or `request.GET.getlist()` – Bobort Apr 06 '18 at 16:05
0

You can use a simple trick just

queryDict._mutable = False
# Change queryDict
your_dict = {'num': [0], 'var1':['value1', 'value2'], 'var2':['8']}
queryDict.upate(your_dict)
# reset the state
queryDict._mutable = True 

I think this will help you better: This QueryDict instance is immutable

Almabud
  • 152
  • 2
  • 9
0
    user_obj = get_object_or_404(NewUser,id=id)
    if request.method == 'POST':
        queryDict = request.POST
        data = dict(queryDict)
        print(data['user_permissions[]'])
        user_obj.user_permissions.clear()
        user_obj.user_permissions.set(data['user_permissions[]'])
        return HttpResponse('Done')
Gaurav Nagar
  • 191
  • 2
  • 4