'Flask-restx request parser returns 400 Bad Request
I'm using flask-restx
in my flask application but each time I use the swagger ui to make a request it returns this 400:
http://127.0.0.1:5000/api/user/register/?password=test&email=test&username=test
{
"message": "Did not attempt to load JSON data because the request Content-Type was not 'application/json'."
}
My file structure:
flask-project/
├─ run.py
├─ app/
│ ├─ main/
│ │ ├─ __init__.py
│ │ ├─ api/
│ │ │ ├─ __init__.py
│ │ │ ├─ user.py
│ ├─ __init__.py
app/_init_.py
import os
from dotenv import load_dotenv
from flask import Flask
# Extensions
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
from flask_socketio import SocketIO
db = SQLAlchemy()
ma = Marshmallow()
socketio = SocketIO()
load_dotenv()
def create_app(debug=False):
from app.main.api import api_blueprint
app = Flask(__name__)
app.debug = debug
app.config['SECRET_KEY'] = os.getenv('SECRET_KEY')
app.config['SQLALCHEMY_DATABASE_URI'] = "sqlite:///database.sqlite3"
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "true" # !! Only in development environment.
db.init_app(app) # Flask-SQLAlchemy must be initialized before Flask-Marshmallow.
ma.init_app(app)
socketio.init_app(app)
app.register_blueprint(api_blueprint, url_prefix='/api')
with app.app_context():
db.create_all()
@app.before_first_request
def create_tables():
""" Pre-populate specific tables """
pass
return app
user.py
from flask_restx import Namespace, Resource, reqparse
api = Namespace('user')
@api.route('/register')
@api.param('username', 'Username')
@api.param('email', 'Email')
@api.param('password', 'Password')
class CreateUser(Resource):
def put(self):
parser = reqparse.RequestParser()
parser.add_argument('username', location='json', type=str)
parser.add_argument('email', location='json', type=str)
parser.add_argument('password', location='json', type=str)
args = parser.parse_args()
return args
When I placed print statements in the put
method, I found that the method is called and anything before I define args will print. After the line where I define args nothing prints. What am I doing wrong?
Solution 1:[1]
I figured out that by downgrading from Werkzeug 2.1.2 to 2.0.2 it fixed the issue.
Solution 2:[2]
I just went through this on a project this weekend.
api.param
is for parameters that are in the path, like /users/<user_id>
. The parameters you are using are query parameters, not path parameters. So remove the 3 @api.param
decorators.
As I understand it, location='json'
is for extracting data from the body of a request sent in JSON. Your parameters are query parameters. Change your parser.add_argument
calls to use location='args'
.Then after calling parse_args()
as you have in your posted code, you should be able to do args['username']
to get the value of the username
query arg, which will give None if username
arg was not given.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Peter |
Solution 2 | PaulMcG |