Làm cách nào để thay đổi django QueryDict thành Python Dict?


111

Hãy giả sử tôi có QueryDict sau:

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

Tôi muốn có một từ điển trong số này, ví dụ:

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

(Tôi không quan tâm xem biểu tượng unicode uvẫn tồn tại hay biến mất.)

Nếu tôi làm như vậy queryDict.dict(), theo đề xuất của trang web django , tôi sẽ mất các giá trị bổ sung thuộc về var1, ví dụ:

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

Tôi đã nghĩ đến việc làm điều này:

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

Có cách nào tốt hơn?

Câu trả lời:


103

Điều này sẽ hoạt động: myDict = dict(queryDict.iterlists())


4
queryDict.iterlists () đang tạo một giá trị danh sách từ mỗi khóa, có thể do bạn có danh sách phổ ?, queryDict.iteritems () nếu bạn biết rằng câu truy vấn không chứa danh sách.
panchicore

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

5
Trong Django 1.6, dict(queryDict.lists())dường như hoạt động
Dan Passaro

39
Trong Django 1.8 trên Python 3, tất cả những gì tôi cần là được dict(queryDict).
fmalina

1
Điều này không hoạt động đối với nhiều thư viện bao gồm cả tác giả. Xem câu hỏi của tôi và câu trả lời của riêng tôi tại đây (hoạt động với v2 và v3 của python): stackoverflow.com/questions/37026535/…
Olivier Pons

193

Hai cách để tìm hiểu, thử hoặc xem nguồn. Câu trả lời là không: dict def (tự): "" "Returns đối tượng hiện tại như một dict với các giá trị duy nhất. """ Trở lại dict ((key, tự [key]) cho khóa tự)
dalore

6
Mặc dù điều này giải quyết vấn đề cho một số người truy cập trang này từ google, nhưng nó không trả lời câu hỏi của OP yêu cầu rõ ràng về việc giữ lại nhiều giá trị cho một khóa.
bạo loạn vào

1
Cảm ơn chúa vì câu trả lời này. Tôi thật không biết gì
Nic Wanavit

Làm việc trên Django 1.11
jobima

16

Đây là những gì tôi đã sử dụng:

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

Từ cách sử dụng của tôi, điều này dường như giúp bạn có được một danh sách mà bạn có thể gửi lại ví dụ như một phương thức khởi tạo biểu mẫu.

CHỈNH SỬA: có thể đây không phải là phương pháp tốt nhất. Có vẻ như nếu bạn muốn ghi QueryDictvào một tệp tin vì bất kỳ lý do điên rồ nào, đó QueryDict.urlencode()là cách tốt nhất. Để tái tạo lại QueryDictbạn chỉ cần làm QueryDict(urlencoded_data).


3
Phương pháp này bị hành vi không xác định; trong tình huống một khóa nhất định có thể có một hoặc nhiều giá trị, đôi khi bạn có thể nhận được một chuỗi và đôi khi nhận được danh sách các chuỗi.
Asherah

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

6

Nếu bạn không muốn các giá trị dưới dạng Mảng, bạn có thể làm như sau:

# 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 là một công cụ mạnh mẽ, hãy đọc thêm về nó tại đây http://docs.python.org/2/library/functions.html#zip


2
Tôi biết điều này đã gần 6 năm tuổi, chỉ cần chỉ ra cho bất kỳ ai đạt được câu trả lời này: Trong Django> = 2.0 (cũng có thể hoạt động trong các phiên bản cũ hơn, đó chỉ là phiên bản tôi đang sử dụng), bạn có thể làm QueryDict.dict()(tức là request.POST.dict()) và nó sẽ trả về các giá trị đúng.
Luca Bezerra

Luca bạn là một huyền thoại. Điều này đã khiến tôi phát điên cả ngày! Của bạn là câu trả lời duy nhất tôi có thể nhận được để làm việc.
scottapotamus ngày

4

Tôi gặp phải sự cố tương tự, muốn lưu các giá trị tùy ý từ một biểu mẫu dưới dạng các giá trị được tuần tự hóa.

Câu trả lời của tôi tránh lặp lại nội dung từ điển một cách rõ ràng: dict(querydict.iterlists())

Để truy xuất một giá trị giống từ điển có chức năng như giá trị ban đầu, một hàm nghịch đảo sử dụng QueryDict.setlist()để điền một giá trị mớiQueryDict giá trị . Trong trường hợp này, tôi không nghĩ rằng việc lặp lại rõ ràng là có thể tránh được.

Các hàm trợ giúp của tôi trông như thế này:

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

Cập nhật:

myDict = dict(queryDict._iterlists())

Xin lưu ý: gạch dưới _trong phương pháp danh sách queryDict. Phiên bản Django: 1.5.1


3

dict(request.POST) trả về một từ điển python kỳ lạ với các giá trị được bao bọc bởi mảng.

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

nơi {x:request.POST.get(x) for x in request.POST.keys()}trả về sản lượng mong đợi.

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

Trong Django> = 2.0 (cũng có thể hoạt động trong các phiên bản cũ hơn, đó chỉ là phiên bản tôi đang sử dụng), bạn có thể làm QueryDict.dict()(tức là request.POST.dict()) và nó sẽ trả về các giá trị đúng.
Luca Bezerra

2

chỉ cần thêm

queryDict=dict(request.GET) hoặc là queryDict=dict(QueryDict)

Trong chế độ xem của bạn và dữ liệu sẽ được lưu trong querDict dưới dạng python Dict.


1

Đây là cách tôi giải quyết vấn đề đó:

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

1

Giống như tôi, bạn có thể quen thuộc hơn với Dict()các phương thức trong python. Tuy nhiên, QueryDict()cũng là một đối tượng dễ sử dụng. Ví dụ: có lẽ bạn muốn nhận giá trị từrequest.GET QueryDict() .

Bạn có thể làm điều này như sau: request.GET.__getitem__(<key>).

QueryDict()tài liệu: https://docs.djangoproject.com/en/2.0/ref/request-response/#django.http.QueryDict


1
Tránh sử dụng các phương pháp gạch dưới kép. Cách nhiều trăn hơn sẽ được sử dụng request.GET.get(<key>)hoặcrequest.GET.getlist(<key>)
Bobort

1

Với Django 2.2một vài giải pháp sạch:

  1. QueryDict.dict()là đơn giản nhất nhưng nó sẽ bị phá vỡ QueryDictvới danh sách dưới dạng giá trị, ví dụ:
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)

sẽ xuất ra

a two  # <--- missed 'one'
b three
  1. dict(QueryDict) tốt hơn vì nó sẽ tạo từ điển danh sách chính xác:
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)

sẽ xuất ra

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

cái nào đúng.


0

Tôi đã thử cả hai dict(request.POST)request.POST.dict()nhận ra rằng nếu bạn có listcác giá trị, ví dụ như được 'var1':['value1', 'value2']lồng trong của bạn request.POST, thì sau ( request.POST.dict()) chỉ cấp cho tôi quyền truy cập vào mục cuối cùng trong danh sách lồng nhau trong khi trước ( dict(request.POST)) cho phép tôi truy cập tất cả các mục trong danh sách lồng nhau.

Tôi hi vọng điêu nay se giup được ai đo.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.