web-dev-qa-db-fra.com

En forme de conversion POST objet dans une représentation appropriée pour mongodb

J'utilise Flask et MongoDB. J'essaie de convertir le contenu de request.form en quelque chose de approprié pour enregistrer via PyMongo. Cela semble être quelque chose qui devrait arriver assez souvent pour avoir une solution toute faite.

Donc, ce que Flask me donne est quelque chose comme:

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

Et ce que je cherche à obtenir est quelque chose de proche:

{
  'default': '',
  'name': ['short_text', 'another'],
  'required': true
}
27
Ivan P
>>> 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) est la chose à garder à l'esprit. Voir la documentation pertinente

28
Vb407

La structure de données Flask ImmutableMultiDict a une méthode to_dict intégrée.

Cette connaissance, en plus de la propriété request de Flask __, propriété form étant une ImmutableMultiDict, permet un traitement simple d'une demande de formulaire POST à MongoDB.

Voir ci-dessous pour un exemple naïf:

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)
18
Joel Colucci

Vous pouvez utiliser getlist de werkzeug pour écrire un code comme celui-ci

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

Désormais, chaque clé de data sera une liste contenant 1 élément supplémentaire. Pour obtenir des résultats exactement dans votre format, faites ceci

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

Cela est maintenant inefficace car pour chaque touche, il y a 3 appels à request.form.getlist(key). Vous pouvez écrire une boucle et la contourner.

17
lovesh

request.form.to_dict() donnerait ce dont vous avez besoin

13
Mellkor
>>> 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'}
1
lod

Comparaison des méthodes dict() et .to_dict() avant et après la version 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')])

Jusqu'à 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'}

Ainsi, 

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

À 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'}

Ainsi,

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

Utiliser .to_dict() avec flat=True/False est une option plus sûre.

0
Rakesh Sharma