无法通过htmx的hx-put在Flask视图中读取hx-include的值
解决htmx PUT请求传递select值到Flask的415错误问题
问题现象
通过htmx的hx-put提交模态框内select元素的值到Flask视图函数时,后端用request.get_json()无法获取数据,控制台出现以下错误:
SyntaxError: Expected property name or '}' in JSON at position 1 (line 1 column 2) at JSON.parse (<anonymous>) at S (htmx.min.js:1:4795) at dr (htmx.min.js:1:34354) at sr (htmx.min.js:1:31612) at ce (htmx.min.js:1:37724) at htmx.min.js:1:21402 at HTMLButtonElement.i (htmx.min.js:1:17838) y @ htmx.min.js:1 S @ htmx.min.js:1 dr @ htmx.min.js:1 sr @ htmx.min.js:1 ce @ htmx.min.js:1 (anonymous) @ htmx.min.js:1 i @ htmx.min.js:1 htmx.min.js:1 PUT http://localhost:5000/lot/update_storage/1 415 (UNSUPPORTED MEDIA TYPE) ce @ htmx.min.js:1 (anonymous) @ htmx.min.js:1 i @ htmx.min.js:1 htmx.min.js:1 Response Status Error Code 415 from /lot/update_storage/1
相关代码如下:
HTML代码
<div class="modal-dialog modal-dialog-centered"> <div class="modal-content"> <div class="modal-header"> <h5 id="muctor" class="modal-title">{{ title }}</h5> <h5 class="modal-title">{{ title }}</h5> </div> <div class="modal-body"> <div class="dropdown"> <select id="selected_storage" name="pavvy" class="form-select form-select-sm" aria-label=".form-select-sm example"> {% for i in items %} <option value="{{ i.id }}">{{ i.name }}</option> {% endfor %} </select> </div> </div> <div><input type="text" id="username" placeholder="Enter your name"></div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button> <button type="button" hx-put="{{ url_for('lots_bp.update_storage', id=id) }}" hx-include="#selected_storage" hx-swap="none" hx-headers="{'Content-Type': 'application/json'}" hx-trigger="click" class="btn btn-sm btn-primary">Submit</button> </div> </div> </div>
Python代码
@lots_bp.route("/update_storage/<int:id>", methods=["PUT"]) def update_storage(id: int): print(request.get_json()) return ""
错误原因
手动设置了hx-headers="{'Content-Type': 'application/json'}",但htmx通过hx-include收集的表单元素数据默认是以application/x-www-form-urlencoded格式发送的,并非JSON格式。这就导致两个问题:
- Flask后端收到非JSON格式的数据,用
request.get_json()无法解析,返回415不支持的媒体类型。 - htmx前端收到后端的错误响应后,尝试将其解析为JSON,进而触发JSON语法错误。
解决方案
方案一:移除JSON头部,使用表单格式接收(推荐)
这种方法更贴合htmx默认的表单数据处理逻辑,无需额外构造JSON:
- 修改HTML中的提交按钮,移除
hx-headers属性:
<button type="button" hx-put="{{ url_for('lots_bp.update_storage', id=id) }}" hx-include="#selected_storage" hx-swap="none" hx-trigger="click" class="btn btn-sm btn-primary">Submit</button>
- 修改Flask视图函数,通过
request.form获取表单数据(select的name属性为pavvy):
@lots_bp.route("/update_storage/<int:id>", methods=["PUT"]) def update_storage(id: int): selected_storage_id = request.form.get('pavvy') print(selected_storage_id) return ""
方案二:构造JSON格式数据发送
如果确实需要发送JSON格式数据,可以通过hx-vals手动构造JSON内容,同时保留正确的请求头:
- 修改HTML提交按钮,用
hx-vals指定JSON数据,注意引号使用(外层用单引号,内层用双引号):
<button type="button" hx-put="{{ url_for('lots_bp.update_storage', id=id) }}" hx-vals='{"pavvy": document.getElementById("selected_storage").value}' hx-headers='{"Content-Type": "application/json"}' hx-swap="none" hx-trigger="click" class="btn btn-sm btn-primary">Submit</button>
- Flask视图函数可以继续使用
request.get_json()获取数据:
@lots_bp.route("/update_storage/<int:id>", methods=["PUT"]) def update_storage(id: int): data = request.get_json() print(data.get('pavvy')) return ""
内容的提问来源于stack exchange,提问作者godhar
相关产品推荐
相关产品推荐

