如何在Python中获取HTML拖拽放置元素的值?
解决拖拽练习到盒子后无法在Flask后端获取值的问题
问题出在表单提交的规则上:
- 你拖拽的
<a>标签是普通HTML元素,不是表单专属控件(比如input、select),表单提交时只会发送表单控件的值,不会处理这些普通元素。 - 给盒子
<div>加的name属性无效,只有表单控件的name才会被表单识别,所以后端request.form.get("C")拿不到任何值,返回None。
要解决这个问题,核心是让拖拽的练习内容变成表单能识别的提交数据,最简单的办法是给每个盒子加一个隐藏的input,用它存储盒子里的练习,表单提交时就会把这些input的值传给后端。
修改后的HTML代码
<h2>Create Workout2</h2> <script> function droppoint(event) { var data = event.dataTransfer.getData("Text"); var nodeCopy = document.getElementById(data).cloneNode(true); nodeCopy.id = data + "-copy"; // 避免页面出现重复ID event.target.appendChild(nodeCopy); // 获取当前盒子对应的隐藏input,更新它的值 const hiddenInput = event.target.querySelector('input[type="hidden"]'); // 允许多个练习,用逗号分隔;如果只允许单个,直接赋值即可 if (hiddenInput.value) { hiddenInput.value += "," + data; } else { hiddenInput.value = data; } event.preventDefault(); } function allowDropOption(event) { event.preventDefault(); } function dragpoint(event) { event.dataTransfer.setData("Text", event.target.id); } </script> <form action="/createworkout2" method="post"> <div class="container text-center"> <div class="row"> <div class="col"> <!-- 下拉菜单部分保持不变 --> <div class="dropdown"> <button class="btn btn-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false"> Cardio </button> <ul class="dropdown-menu"> {% for cardio in cardio %} <li><a class="dropdown-item" draggable="true" id="{{ cardio.exercise }}" ondragstart="dragpoint(event)">{{ cardio.exercise }}</a></li> {% endfor %} </ul> </div> <div class="dropdown"> <button class="btn btn-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false"> Tone </button> <ul class="dropdown-menu"> {% for tone in tone %} <li><a class="dropdown-item" draggable="true" id="{{ tone.exercise }}" ondragstart="dragpoint(event)">{{ tone.exercise }}</a></li> {% endfor %} </ul> </div> <div class="dropdown"> <button class="btn btn-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false"> Bulk </button> <ul class="dropdown-menu"> {% for bulk in bulk %} <li><a class="dropdown-item" draggable="true" id="{{ bulk.exercise }}" ondragstart="dragpoint(event)">{{ bulk.exercise }}</a></li> {% endfor %} </ul> </div> </div> <div class="col"> <div class="container"> <!-- 每个盒子添加隐藏input,name和盒子标识一致 --> <div class="box" ondrop="droppoint(event)" ondragover="allowDropOption(event)"> A <input type="hidden" name="A" value=""> </div> <div class="box" ondrop="droppoint(event)" ondragover="allowDropOption(event)"> B <input type="hidden" name="B" value=""> </div> <div class="box" ondrop="droppoint(event)" ondragover="allowDropOption(event)"> C <input type="hidden" name="C" value=""> </div> <div class="box" ondrop="droppoint(event)" ondragover="allowDropOption(event)"> D <input type="hidden" name="D" value=""> </div> <div class="box" ondrop="droppoint(event)" ondragover="allowDropOption(event)"> E <input type="hidden" name="E" value=""> </div> <div class="box" ondrop="droppoint(event)" ondragover="allowDropOption(event)"> F <input type="hidden" name="F" value=""> </div> <div class="box" ondrop="droppoint(event)" ondragover="allowDropOption(event)"> G <input type="hidden" name="G" value=""> </div> <div class="box" ondrop="droppoint(event)" ondragover="allowDropOption(event)"> H <input type="hidden" name="H" value=""> </div> </div> </div> </div> </div> <button class="btn btn-primary" type="submit">Confirm</button> </form>
修改后的Flask后端代码
如果盒子允许多个练习,需要把逗号分隔的字符串拆分成列表:
@app.route("/createworkout2", methods=["GET", "POST"]) @login_required def createworkout2(): """View and edit personal workouts""" cardio = db.execute("SELECT exercise FROM exercises WHERE type LIKE '%cardio%'") tone = db.execute("SELECT exercise FROM exercises WHERE type LIKE '%tone%'") bulk = db.execute("SELECT exercise FROM exercises WHERE type LIKE '%bulk%'") if request.method == "POST": # 获取盒子C的练习内容 activity1 = request.form.get("C") if activity1: # 拆分多个练习为列表 exercises_c = activity1.split(",") flash(f"Box C exercises: {', '.join(exercises_c)}") else: flash("Box C has no exercises") return redirect("/") else: return render_template("createworkout2.html", cardio=cardio, tone=tone, bulk=bulk)
额外说明
- 克隆元素时修改了ID(
data + "-copy"),避免页面出现重复ID的元素,符合HTML规范。 - 如果每个盒子只允许一个练习,直接覆盖隐藏input的值即可,去掉逗号拼接的逻辑。
- 移除了下拉菜单
<ul>上冗余的draggable和ondragstart属性,这些只需要加在<a>标签上即可。
内容的提问来源于stack exchange,提问作者AndyM
相关产品推荐
相关产品推荐

