Django, Python: есть ли простой способ преобразовать ключи POST в квадратных скобках в стиле PHP в многомерный dict?

В частности, у меня есть форма, которая вызывает службу Django (написанную с использованием Piston, но я не думаю, что это актуально), отправляя через POST что-то вроде этого:

edu_type[3][name] => a
edu_type[3][spec] => b
edu_type[3][start_year] => c
edu_type[3][end_year] => d
edu_type[4][0][name] => Cisco
edu_type[4][0][spec] => CCNA
edu_type[4][0][start_year] => 2002
edu_type[4][0][end_year] => 2003
edu_type[4][1][name] => fiju
edu_type[4][1][spec] => briju
edu_type[4][1][start_year] => 1234
edu_type[4][1][end_year] => 5678

Я хотел бы обработать это на стороне Python, чтобы получить что-то вроде этого:

edu_type = {
    '3' : { 'name' : 'a', 'spec' : 'b', 'start_year' : 'c', end_year : 'd' },
    '4' : {
        '0' : { 'name' : 'Cisco', 'spec' : 'CCNA', 'start_year' : '2002', 'end_year' : '2003' },
        '1' : { 'name' : 'fiju', 'spec' : 'briju', 'start_year' : '1234', 'end_year' : '5678' },
    },
}

Есть идеи? Спасибо!


person Berislav Lopac    schedule 11.12.2009    source источник
comment
Я не понимаю, что вы хотите сделать. Диктовка, которую вы хотите ниже, действует так же, как та, что у вас есть выше. Какие исходные данные? Что вы подразумеваете под ключами POST в скобках в стиле PHP?   -  person McPherrinM    schedule 12.12.2009
comment
HTTP POST (PUT, но здесь не имеет значения) позволяет отправлять пары имя/значение в виде строк. Приведенный выше код представляет собой один такой POST со строками имен слева и значениями справа. В PHP используется трюк, упрощающий передачу многомерных массивов через POST-запросы: когда синтаксис, подобный приведенному выше, отправляется в PHP-скрипт с помощью POST, он сразу же становится доступным в суперглобальной переменной $_POST как собственный массив. Из-за этой уловки PHP-программисты часто не думают дважды при отправке данных, что и является проблемой, с которой я здесь столкнулся — у меня нет доступа к вызывающему коду.   -  person Berislav Lopac    schedule 12.12.2009
comment
так вы получаете данные в виде строки, которая выглядит как код в вашем первом блоке кода? или вы получаете объекты Python?   -  person andylei    schedule 12.12.2009
comment
Все верно, за исключением того, что это не одна строка, а пары ключ/значение, полученные через POST-запрос. Чтобы упростить задачу, давайте представим, что у меня есть словарь, похожий на первый пример, и я хочу превратить его во второй.   -  person Berislav Lopac    schedule 12.12.2009
comment
поэтому для этих пар ключ-значение edu_type[3][end_year] будет ключом, а значением будет d. это правильно?   -  person andylei    schedule 12.12.2009
comment
Вот так; Я извиняюсь за использование бессмысленных значений, я просто использую их для тестирования передачи. В моем приложении должен быть фактический год (если он не считается пустым значением), но это не имело значения для этой проблемы.   -  person Berislav Lopac    schedule 12.12.2009


Ответы (4)


Я сделал небольшой парсер на питоне для обработки многомерных диктов, вы можете найти его по адресу https://github.com/bernii/querystring-parser

person berni    schedule 18.05.2011
comment
Спасибо, это похоже на решение, которое я искал! :) - person Berislav Lopac; 19.05.2011

Dottedish делает что-то вроде того, что вы хотите. http://pypi.python.org/pypi/dottedish. На самом деле у него нет домашней страницы, но вы можете установить его из pypi или загрузить исходный код с github.

>>> import dottedish
>>> dottedish.unflatten([('3.name', 'a'), ('3.spec', 'b')])
{'3': {'name': 'a', 'spec': 'b'}}
person joeforker    schedule 08.02.2010

Я исхожу из предыдущего ответа Atli об использовании PHP json_encode...

Словарь Python в своей самой базовой форме синтаксически идентичен JSON. Вы можете легко выполнить eval() в структуре JSON, чтобы создать словарь Python:

>>> blob = """{
...     '3' : { 'name' : 'a', 'spec' : 'b', 'start_year' : 'c', 'end_year' : 'd' },
...     '4' : {
...         '0' : { 'name' : 'Cisco', 'spec' : 'CCNA', 'start_year' : '2002', 'end_year' : '2003' },
...         '1' : { 'name' : 'fiju', 'spec' : 'briju', 'start_year' : '1234', 'end_year' : '5678' },
...     },
... }"""
>>> edu_type = eval(blob)
>>> edu_type
{'3': {'end_year': 'd', 'start_year': 'c', 'name': 'a', 'spec': 'b'}, '4': {'1': {'end_year': '5678', 'start_year': '1234', 'name': 'fiju', 'spec': 'briju'}, '0': {'end_year': '2003', 'start_year': '2002', 'name': 'Cisco', 'spec': 'CCNA'}}}

Теперь, это лучший способ? Возможно нет. Но он работает и не прибегает к регулярным выражениям, что может быть технически лучше, но определенно не является более быстрым вариантом, учитывая время, затрачиваемое на отладку и устранение неполадок при сопоставлении с шаблоном.

JSON — хороший формат для межстраничной передачи данных.

Python также имеет модуль json как часть стандартной библиотеки. Хотя это более требовательно к анализируемому вами выводу, это, безусловно, лучший способ сделать это (хотя и требует больше работы).

person jathanism    schedule 11.12.2009

ладно, это чертовски гетто, но вот:

скажем, ваш ввод представляет собой список кортежей. скажем: input = [('edu_type[3][end_year]', 'd'), ...]

from collections import defaultdict
from re import compile

def defdict():
    return defaultdict(defdict)
edu_type = defdict()

inputs = [(x.replace('[', '["').replace(']', '"]'), y) for x, y in input]
for input in inputs:
    exec = '%s = "%s"' % input

Обратите внимание, что вы должны использовать это только в том случае, если вы доверяете источнику ввода, так как это далеко не безопасно.

person andylei    schedule 12.12.2009