Axios 数据在发送到 Flask POST 路由时以 ImmutableMultiDict([]) 的形式出现,但与 Postman 一起使用

Posted

技术标签:

【中文标题】Axios 数据在发送到 Flask POST 路由时以 ImmutableMultiDict([]) 的形式出现,但与 Postman 一起使用【英文标题】:Axios data coming up as ImmutableMultiDict([]) when sent to Flask POST route, but work with Postman 【发布时间】:2019-07-20 09:51:56 【问题描述】:

我正在使用 Flask 创建一个 POST 方法来在我的 mysql 数据库中注册一个新用户。我尝试创建一个 Axios 方法来从我的 React JS 应用程序发送 POST 请求。我正在使用 Postman 进行测试,并使用 application/x-www-form-urlencoded 发送它。注册在 Postman 中有效,但数据显示为 ImmutableMultiDict([])

烧瓶代码:

@app.route('/registerUser', methods=['POST'])
def registerUser():
    data = request.form
        if len(data) is 0:
            return 'Request was empty!'
        username = data['username']
        password = data['password']
        email = data['email']
        user = User(username=username, 
                    password=password, 
                    email=email)
        db.session.add(user)
        db.session.commit()
        return 'Registration success!'
    return 'Registration failed!'

反应代码:

class Signup extends Component 
    constructor(props)
        super(props);
        this.state = 
            username: '',
            password: '',
            email: ''
        
        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
        this.clearInputs = this.clearInputs.bind(this);
    

    handleChange(event)
        event.preventDefault();
        this.setState([event.target.name]: event.target.value);
    
    handleSubmit(event)
        event.preventDefault();
        const config = 
            headers:  'content-type': 'application/x-www-form-urlencoded' 
        
        axios.post(`http://localhost:5000/registerUser`, 
            this.state, config)
             .then(res => 
                alert(res.data);
             )
             .catch((err) => 
                alert(err);
             );
    

    render()
        return (
            <div className='signup'>
                <form onSubmit=this.handleSubmit>
                    <label>
                        Username
                        <input type='text' name='username' 
                               value=this.state.username
                               onChange=this.handleChange/><br/>
                    </label>
                    <label>
                        Password
                        <input type='password' name='password' 
                               value=this.state.password 
                               onChange=this.handleChange/><br/>
                    </label>
                    <label>
                        Email
                        <input type='text' name='email' 
                               value=this.state.email
                               onChange=this.handleChange/><br/>
                    </label>
                    <input type='submit' value='Submit' /><br/>
                </form>
            </div>
        );
    


export default Signup;

为什么没有正确从 Axios 发送数据?我在烧瓶中使用 CORS,Postman 和 Axios 应该发送相同的表单数据。

编辑:我将 POST 请求更改为使用 request.form 但是,Postman 有效,但 Axios 仍然无效。 来自邮递员:

ImmutableMultiDict([('username', 'person'), ('password', 'Password1'), ('email', 'example@example.com')])

来自 Axios:ImmutableMultiDict([('"username":"someone","password":"Password1","email":"email@example.com"', '')])

Axios 是否配置错误?

【问题讨论】:

【参考方案1】:

我发现了问题所在。默认情况下,Axios 以 JSON 格式发送数据。为了符合 urlencoded,您需要构建一个新的 URLSearchParams 对象来代替发送。见documentation

这是有效的 React 代码:

handleSubmit(event)
    event.preventDefault();
    const config = 
        headers:  'content-type': 'application/x-www-form-urlencoded' 
    
    const getParams = (obj) => 
        const params = new URLSearchParams();
        const keys = Object.keys(obj);
        for(let k of keys)
            params.append(k, obj[k]);
        
        return params;
    
    axios.post(`http://localhost:5000/registerUser`, 
        getParams(this.state), config)
         .then(res => 
            alert(res.data);
            this.clearInputs();
         )
         .catch((err) => 
            alert(err);
         );

这适用于我的 OP Flask 代码。

【讨论】:

【参考方案2】:

我认为您将不得不将请求数据强制转换为 registerUser 路由中的类型​​ JSON,因为您尝试访问 JSON 响应但您在 @987654324 中发送了请求@ 格式。 application/x-www-form-urlencoded 是由W3C 创建的default 表单内容类型规范,通常用于发送文本/ASCII 数据。也许您可以尝试以下操作,看看是否得到预期的JSON 响应:

app.route('/registerUser', methods=['POST'])
def registerUser():
    requestJson = request.get_json(force=True)

    # check that requestJson is correct if so
    # create and save your new user to your db

    return 'Registration failed!'

如果您的requestJson 符合预期,那么您只需提取必填字段并将新用户保存到数据库中即可。如果不是,请打印出您收到的请求,看看如何正确解析它。

希望对您有所帮助!

【讨论】:

确实有帮助。我使用了 Postman 的表单数据,它可以工作,但是,请参阅我对新错误的编辑。 Axios 正在发送 obj 对象并返回一个不完美的 JSON 对象。 request.form.keys()[0] 打印出什么?我将假设:"obj":"username":"uernmf","password":"Password12!","email":"k@ao.com"' 我得到:TypeError: 'dict_keyiterator' object is not subscriptable 查看我的新编辑。令我困惑的是我如何告诉 Axios 发送 urlencoded,但它显然是 JSON 数据。我不想将 Flask 代码更改为使用 JSON,因为这会破坏目的。 好的,所以你现在正在使用 request.form。你能打印 request.form[0] 并粘贴进去吗?它应该删除数组并返回元组

以上是关于Axios 数据在发送到 Flask POST 路由时以 ImmutableMultiDict([]) 的形式出现,但与 Postman 一起使用的主要内容,如果未能解决你的问题,请参考以下文章

在Python Flask中,Axios POST没有被正确解析。

flask axios post返回http状态码405/400

axios 不会将 post 数据发送到后端

无法接收 Vue 通过 axios 发送到 PHP 的 Post 数据

Axios Post 请求发送未定义

反应 axios 从 Flask 后端获取空数据