จะเปลี่ยน 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 () กำลังสร้างค่ารายการจากแต่ละคีย์อาจเป็นเพราะคุณ spect list?, queryDict.iteritems () ถ้าคุณรู้ว่า querydict ไม่มี list
panchicore

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

5
ใน Django 1.6 dict(queryDict.lists())ดูเหมือนจะใช้งานได้
Dan Passaro

39
ใน Django 1.8 บน Python 3 สิ่งที่ฉันต้องการคือdict(queryDict).
fmalina

1
สิ่งนี้ใช้ไม่ได้กับไลบรารีจำนวนมากรวมถึงอัตโนมัติ ดูคำถามของฉันและคำตอบของฉันที่นี่ (ใช้ได้กับ v2 และ v3 ของ python): stackoverflow.com/questions/37026535/…
Olivier Pons

194

สองวิธีในการค้นหาลองใช้หรือดูแหล่งที่มา คำตอบคือไม่: def dict (self): "" "ส่งคืนวัตถุปัจจุบันเป็น dict ที่มีค่าเอกพจน์" "" return dict ((key, self [key]) for key in self)
dalore

6
แม้ว่าวิธีนี้จะช่วยแก้ปัญหาสำหรับบางคนที่เข้ามาในหน้านี้จาก google แต่ก็ไม่ได้ตอบคำถามของ OP ซึ่งขอให้รักษาค่าหลายค่าสำหรับคีย์อย่างชัดเจน
จลาจล

1
ขอบคุณพระเจ้าสำหรับคำตอบนี้ ฉันไม่รู้เลย
Nic Wanavit

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

จากการใช้งานของฉันดูเหมือนว่าคุณจะได้รับรายการที่คุณสามารถส่งกลับไปได้เช่นตัวสร้างแบบฟอร์ม

แก้ไข:นี่อาจไม่ใช่วิธีที่ดีที่สุด ดูเหมือนว่าถ้าคุณต้องการเขียนQueryDictลงไฟล์ด้วยเหตุผลบ้าๆอะไรก็ตามQueryDict.urlencode()เป็นวิธีที่จะไป ที่จะสร้างคุณก็ทำQueryDictQueryDict(urlencoded_data)


3
วิธีนี้ทนทุกข์ทรมานจากพฤติกรรมที่ไม่แน่นอน ในสถานการณ์ที่คีย์หนึ่ง ๆ อาจมีค่าตั้งแต่หนึ่งค่าขึ้นไปบางครั้งคุณอาจได้รับสตริงและบางครั้งก็ได้รับรายการสตริง
Asherah


6

หากคุณไม่ต้องการให้ค่าเป็น Arrays คุณสามารถทำสิ่งต่อไปนี้:

# 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()) และมัน จะคืนค่าอย่างถูกต้อง
Luca Bezerra

Luca คุณคือตำนาน สิ่งนี้ทำให้ฉันคลั่งไคล้มาตลอดทั้งวัน! คุณคือคำตอบเดียวที่ฉันจะได้ทำงาน
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

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()) และจะส่งคืนค่าอย่างถูกต้อง
Luca Bezerra

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()วิธีการใน python มากกว่า อย่างไรก็ตามQueryDict()ยังเป็นวัตถุที่ใช้งานง่าย ตัวอย่างเช่นคุณอาจต้องการรับค่าจากไฟล์request.GET QueryDict() .

คุณสามารถทำได้ดังนี้: request.GET.__getitem__(<key>).

QueryDict()เอกสารประกอบ: https://docs.djangoproject.com/en/2.0/ref/request-response/#django.http.QueryDict


1
หลีกเลี่ยงการใช้วิธีขีดสองขีด ยิ่งใช้วิธี pythonic request.GET.get(<key>)หรือrequest.GET.getlist(<key>)
Bobort

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)) อนุญาตให้ฉันเข้าถึงรายการทั้งหมดในรายการที่ซ้อนกัน

ฉันหวังว่านี่จะช่วยใครบางคนได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.