En un matraz, convertir el objeto POST de formulario en una representación adecuada para mongodb

Estoy usando Flask y MongoDB. Estoy tratando de convertir el contenido de request.form en algo adecuado para guardar a través de PyMongo. Parece algo que debería aparecer con la frecuencia suficiente para tener una solución lista para usar.

Así que lo que Flask me da es algo como:

ImmutableMultiDict([('default', u''), ('required': u'on'), ('name', u'short_text'), ('name', u'another'), ('submit', u'Submit')]) 

Y lo que busco obtener es algo cercano a esto:

 { 'default': '', 'name': ['short_text', 'another'], 'required': true } 

 >>> from werkzeug.datastructures import ImmutableMultiDict >>> imd = ImmutableMultiDict([('default', u''), ('required', u'on'), ('name', u'short_text'), ('name', u'another'), ('submit', u'Submit')]) >>> imd.to_dict(flat=False) >>> {'default': [''], 'name': ['short_text', 'another'], 'required': ['on'], 'submit': ['Submit']} 

.to_dict(flat=False) es lo que hay que tener en cuenta. Ver la documentación relevante.

La estructura de datos de Flask ImmutableMultiDict tiene un método integrado en to_dict .

Este conocimiento, además de que la propiedad de form objeto de request Flask es un ImmutableMultiDict permite el manejo sencillo de un formulario de solicitud POST a MongoDB.

Vea a continuación un ejemplo ingenuo:

 from flask import request @app.route('/api/v1/account', methods=['POST']) def create_account(): """Create user account""" account_dict = request.form.to_dict() db.account.insert_one(account_dict) 

Puedes usar la lista de obtención de werkzeug para escribir código como este

 data = dict((key, request.form.getlist(key)) for key in request.form.keys()) 

Ahora cada clave de data sería una lista que contendría 1 elemento más. Para obtener resultados exactamente en su formato haga esto

 data = dict((key, request.form.getlist(key) if len(request.form.getlist(key)) > 1 else request.form.getlist(key)[0]) for key in request.form.keys()) 

Ahora esto es ineficiente porque para cada clave hay 3 llamadas a request.form.getlist(key) . Puedes escribir un bucle y sortearlo.

request.form.to_dict() daría lo que necesitas

 >>> from werkzeug.datastructures import ImmutableMultiDict >>> so = ImmutableMultiDict([('default', u''), ('required', u'on'), ('name', u'short_text'), ('name', u'another'), ('submit', u'Submit')]) # Most earlier answers have comments suggesting so.to_dict() # It doesn't work, duplicates are lost like in a normal dict >>> so.to_dict() {'default': '', 'required': 'on', 'name': 'short_text', 'submit': 'Submit'} # The response by Vb407 is better but litters lists everywhere >>> dso = dict(so) {'default': [''], 'required': ['on'], 'name': ['short_text', 'another'], 'submit': ['Submit']} # We can achieve the requested state by cleaning this up >>> { k: dso[k][0] if len(dso[k]) <= 1 else dso[k] for k in dso } {'default': '', 'required': 'on', 'name': ['short_text', 'another'], 'submit': 'Submit'} 

Comparación del método dict() y .to_dict() antes y después de la versión 3.6 de python.

 from werkzeug.datastructures import ImmutableMultiDict imd = ImmutableMultiDict([('default', u''), ('required', u'on'), ('name', u'short_text'), ('name', u'another'), ('submit', u'Submit')]) 

Hasta python3.5

 dict(imd) #output: {'default': [''], 'required': ['on'], 'name': ['short_text', 'another'], 'submit': ['Submit']} imd.to_dict(flat=false) #output: {'default': [''], 'required': ['on'], 'name': ['short_text', 'another'], 'submit': ['Submit']} imd.to_dict(flat=True) # or imd.to_dict() #output: {'default': '', 'required': 'on', 'name': 'short_text', 'submit': 'Submit'} 

Así,

 dict(imd) == imd.to_dict(flat=False) #output: True 

A partir de python3.6.

 dict(imd) #output: {'default': '', 'required': 'on', 'name': 'short_text', 'submit': 'Submit'} imd.to_dict(flat=false) #output: {'default': [''], 'required': ['on'], 'name': ['short_text', 'another'], 'submit': ['Submit']} imd.to_dict(flat=True) # or imd.to_dict() #output: {'default': '', 'required': 'on', 'name': 'short_text', 'submit': 'Submit'} 

Así,

 dict(imd) == imd.to_dict(flat=False) #output: False 

Usar .to_dict() con flat=True/False es una opción más segura.

Una vez que tenga un diccionario de Python, es relativamente sencillo transformarlo en JSON. Suponiendo que tu diccionario es mdict :

 import json mdict = {'default' : u'', 'required': u'on', 'name': u'short_text', 'name': u'another', 'submit': u'Submit'} json_value = json.dumps(mdict, separators=(',',':')) 

PD : Creo que los dicts mutables tienen un método to_dict () para convertirlos en un diccionario regular.