web-dev-qa-db-fra.com

Flacon python-reposant POST ne pas prendre d'arguments JSON

Je suis très nouveau à Flask (& Flask-Restful). 

Mon problème: les arguments json pour une POST sont définis à NONE (ne fonctionne pas).

Je suis capable de prendre des arguments à partir du form-data, en utilisant le plugin POSTMAN pour chrome. Mais, lorsque je passe à raw (& feed a json), il ne parvient pas à lire le json & assigne une NONE à tous mes arguments.

J'ai lu des articles liés à stackoverflow liés à ceci: link1 , link2 , link3 ... aucun de ceux-ci ne m'a aidé.

J'utilise python-2.6, Flask-Restful-0.3.3, Flask-0.10.1, Chrome, POSTMAN sur Oracle Linux 6.5.

Code Pythonapp.py

from flask import Flask, jsonify
from flask_restful import reqparse, abort, Api, Resource

app = Flask(__name__)
api = Api(app)

parser = reqparse.RequestParser()
parser.add_argument('username', type=str)
parser.add_argument('password', type=str)

class HelloWorld(Resource):
    def post(self):
        args = parser.parse_args()
        un = str(args['username'])
        pw = str(args['password'])
        return jsonify(u=un, p=pw)

api.add_resource(HelloWorld, '/testing')

if __== '__main__':
    app.run(Host='0.0.0.0', port=5444 ,debug=True)

Test this en utilisant POSTMAN:

  • Utiliser form-data: fonctionne parfaitement!
  • Utilisation de raw -> json: cause ce problème

Les choses essayées # 1

Ajoutez le paramètre json à ma méthode add_argument() dans app.py

parser = reqparse.RequestParser()
parser.add_argument('username', type=str, location='json') # added json
parser.add_argument('password', type=str, location='json') # added json

Input: {"nom d'utilisateur": "bonjour", "mot de passe": "monde"}

Output: {"p": "Aucun", "u": "Aucun"}

Les choses essayées # 2

Remplacez le type par unicode dans la méthode add_argument() dans app.py

parser = reqparse.RequestParser()
parser.add_argument('username', type=unicode, location='json') # change type to unicode
parser.add_argument('password', type=unicode, location='json') # change type to unicode

Input: {"nom d'utilisateur": "bonjour", "mot de passe": "monde"}

Output: {"p": "Aucun", "u": "Aucun"}


PS: Je continuerai à mettre à jour ma question à chaque tentative infructueuse. S'il vous plaît laissez-moi savoir si vous avez besoin de plus d'informations pour rendre cette question plus claire.

17
sudhishkr

Selon la documentation de Request.json et le nouveau Request.get_json , le type MIME de votre demande POST doit être défini sur application/json. C’est la seule façon pour flask d’analyser automatiquement vos données JSON dans la propriété Request.json qui (je crois) est ce dont dépend Flask-Restful pour récupérer les données JSON. 

REMARQUE: La nouvelle fonction get_json dispose d'une option permettant de forcer l'analyse des données POST au format JSON, quel que soit le type de mim

18
junnytony

la réponse de junnytony m'a donné un indice et je suis allé de l'avant avec cette approche. get_json semble avoir fait le tour. 

from flask import Flask, jsonify, request
from flask_restful import reqparse, abort, Api, Resource

app = Flask(__name__)
api = Api(app)

#parser = reqparse.RequestParser()
#parser.add_argument('username', type=unicode, location='json')
#parser.add_argument('password', type=unicode, location='json')

class HelloWorld(Resource):
    def post(self):
        json_data = request.get_json(force=True)
        un = json_data['username']
        pw = json_data['password']
        #args = parser.parse_args()
        #un = str(args['username'])
        #pw = str(args['password'])
        return jsonify(u=un, p=pw)

api.add_resource(HelloWorld, '/testing')

if __== '__main__':
    app.run(Host='0.0.0.0', port=5444 ,debug=True)
8
sudhishkr

J'ai rencontré un problème similaire et voici une solution qui fonctionne pour moi. Disons que votre application ressemble à ceci:

from flask import Flask, jsonify
from flask_restful import Api, Resource, reqparse

app = Flask(__name__)
api = Api(app)

# Define parser and request args
parser = reqparse.RequestParser()
parser.add_argument('last_name', type=str)
parser.add_argument('first_name', type=str)
# not the type=dict
parser.add_argument('personal_data', type=dict)


class Item(Resource):

    def post(self):

        args = parser.parse_args()

        ln = args['last_name']
        fn = args['first_name']
        # we can also easily parse nested structures
        age = args['personal_data']['age']
        nn = args['personal_data']['nicknames']

        return jsonify(fn=fn, ln=ln, age=age, nn=nn)


api.add_resource(Item, '/item')

if __== '__main__':
    app.run(debug=True)

Maintenant, vous pouvez facilement créer des données JSON:

import json

d = {'last_name': 'smith', 'first_name': 'john', 'personal_data': {'age': 18, 'height': 180, 'nicknames': ['johnny', 'grandmaster']}}

print(json.dumps(d, indent=4))

{
    "last_name": "smith",
    "first_name": "john",
    "personal_data": {
        "age": 18,
        "height": 180,
        "nicknames": [
            "johnny",
            "grandmaster"
        ]
    }
}

json.dumps(d)
'{"last_name": "smith", "first_name": "john", "personal_data": {"age": 18, "height": 180, "nicknames": ["johnny", "grandmaster"]}}'

et appelez l'application:

curl http://localhost:5000/item -d '{"last_name": "smith", "first_name": "john", "personal_data": {"age": 18, "height": 180, "nicknames": ["johnny", "grandmaster"]}}'

Cela va planter avec l'erreur (j'ai raccourci le retraçage):

age = args ['personal_data'] ['age']
TypeError: l'objet 'NoneType' n'est pas souscriptable

la raison en est que l'en-tête n'est pas spécifié. Si on ajoute le 

-H "Content-Type: application/json"

et ensuite appeler

curl http://localhost:5000/item -H "Content-Type: application/json" -d '{"last_name": "smith", "first_name": "john", "personal_data": {"age": 18, "height": 180, "nicknames": ["johnny", "grandmaster"]}}'

La sortie ressemble comme prévu:

{
  "age": 18, 
  "fn": "john", 
  "ln": "smith", 
  "nn": [
    "johnny", 
    "grandmaster"
  ]
}

La fonction peut également être simplifiée pour:

class Item(Resource):

    def post(self):

        json_data = request.get_json()
        # create your response below

comme montré ci-dessus .

1
Cleb