Flask-RESTful如何获取HTML表单输入作为API请求数据
问题原因
原生HTML表单提交POST请求时,默认Content-Type为application/x-www-form-urlencoded,参数以键值对形式编码在请求体中,不是JSON格式。你当前的Flask-RESTful接口默认仅解析application/json类型请求里的from/to/amount参数,所以直接提交表单会触发Content-Type不匹配的报错。
解决方法
两种方案按需选择即可:
方案1:前端拦截表单默认提交,手动发送JSON请求(后端代码不用改)
给表单绑定提交事件,阻止默认的表单跳转提交逻辑,读取输入值组装成接口要求的JSON结构,用fetch发POST请求,逻辑和你用requests调用接口完全一致。
代码示例:
<form id="transferForm" action="{{ url_for('transfer-api') }}" method="post"> <p>Sender account id:</p> <p><input type="text" name="senderId" id="senderId" minlength="20" maxlength="20"/> * 20 characters</p> <p>Receiver account id:</p> <p><input type="text" name="receiverId" id="receiverId" minlength="20" maxlength="20"/> * 20 characters</p> <p>Amount:</p> <p><input type="text" name="amount" id="amount" /> * number</p> <input type="submit" value="transfer" /> </form> <script> const transferForm = document.getElementById('transferForm'); transferForm.addEventListener('submit', async (e) => { // 阻止表单默认提交跳转 e.preventDefault(); // 组装接口要求的参数,注意接口字段是from/to,和表单输入框的name不一致,要手动映射 const requestData = { from: document.getElementById('senderId').value.trim(), to: document.getElementById('receiverId').value.trim(), amount: Number(document.getElementById('amount').value.trim()) }; try { const resp = await fetch(transferForm.action, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(requestData) }); const result = await resp.json(); console.log('接口返回:', result); // 后续自行添加业务逻辑,比如成功提示、页面跳转等 } catch (err) { console.error('请求出错:', err); } }) </script>
*注意:你接口接收的转出/转入账户字段名是from和to,和现有表单输入框的name属性senderId/receiverId不一致,组装参数时必须做字段映射,否则会传参错误。
方案2:修改后端参数解析逻辑,同时兼容表单和JSON请求(前端原生表单不用加JS)
Flask-RESTful的reqparse支持指定参数的解析位置,你只要在定义参数规则时,把location设置为同时支持json和form,就能自动适配两种请求格式——不管是requests发的JSON请求,还是原生表单提交的form参数,都能正常解析。
后端代码修改示例:
from flask_restful import reqparse class Transfer(Resource): def post(self): parser = reqparse.RequestParser() # 配置参数同时从JSON和表单数据中解析 parser.add_argument('from', required=True, location=['json', 'form']) parser.add_argument('to', required=True, location=['json', 'form']) parser.add_argument('amount', required=True, type=float, location=['json', 'form']) args = parser.parse_args() # 保留原有业务逻辑即可 # ... return resp api.add_resource(Transfer, "/api/transfer", endpoint="transfer-api")
*注意:用这个方案需要把表单里对应输入框的name属性改成和接口字段一致,也就是把senderId改为from、receiverId改为to,否则表单提交的键名和接口接收的键名不匹配,会拿不到参数。对应表单输入项修改示例:
<p><input type="text" name="from" id="senderId" minlength="20" maxlength="20"/> * 20 characters</p> <p><input type="text" name="to" id="receiverId" minlength="20" maxlength="20"/> * 20 characters</p>
内容的提问来源于stack exchange,提问作者anon
相关产品推荐
相关产品推荐

