How to change a django QueryDict to Python Dict?
Question:
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?
Answers:
This should work: myDict = dict(queryDict.iterlists())
New in Django >= 1.4.
QueryDict.dict()
https://docs.djangoproject.com/en/stable/ref/request-response/#django.http.QueryDict.dict
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
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
Update:
myDict = dict(queryDict._iterlists())
Please Note : underscore _
in iterlists method of queryDict
. Django version :1.5.1
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)
.
from django.utils import six
post_dict = dict(six.iterlists(request.POST))
dict(request.POST)
returns a weird python dictionary with array wrapped values.
{'start': ['2017-01-14T21:00'], 'stop': ['2017-01-14T22:00'], 'email': ['[email protected]']}
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': '[email protected]'}
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()}
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
just simply add
queryDict=dict(request.GET)
or queryDict=dict(QueryDict)
In your view and data will be saved in querDict as python Dict.
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.
With Django 2.2
there are few clean solutions:
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
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.
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
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')
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?
This should work: myDict = dict(queryDict.iterlists())
New in Django >= 1.4.
QueryDict.dict()
https://docs.djangoproject.com/en/stable/ref/request-response/#django.http.QueryDict.dict
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
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
Update:
myDict = dict(queryDict._iterlists())
Please Note : underscore _
in iterlists method of queryDict
. Django version :1.5.1
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)
.
from django.utils import six
post_dict = dict(six.iterlists(request.POST))
dict(request.POST)
returns a weird python dictionary with array wrapped values.
{'start': ['2017-01-14T21:00'], 'stop': ['2017-01-14T22:00'], 'email': ['[email protected]']}
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': '[email protected]'}
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()}
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
just simply add
queryDict=dict(request.GET)
or queryDict=dict(QueryDict)
In your view and data will be saved in querDict as python Dict.
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.
With Django 2.2
there are few clean solutions:
QueryDict.dict()
is simplest but it will breakQueryDict
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
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.
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
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')