通过Flask后端将来自JavaScript前端的HTML表单数据发送到MySQL数据库时出错
在尝试通过Flask后端,将带有JS前端的HTML表单数据发送到MySQL数据库时,我在浏览器的开发者工具控制台遇到了错误“400 (BAD REQUEST)”。
HTML表单:
<form id="form" method="POST">
<label> Date ID </label>
<input type="text" id="dateID" name="dateID">
<br>
<label> Day of the Week </label>
<input type="text" id="week_day" name="week_day">
<br>
<label> Day </label>
<input type="date" id="day" name="day">
<br>
<label> Rate </label>
<input type="text" id="rate" name="rate">
<br>
<input type="submit">
</form>
JS前端:
const form = document.getElementById("form")
document.getElementById('form').addEventListener('submit', function(e) {
e.preventDefault()
const dateID = document.getElementById('dateID').value
const weekDay = document.getElementById('week_day').value
const day = document.getElementById('day').value
const rate = document.getElementById('rate').value
const formData = new FormData(form)
//console.log(formData.values)
const url = "http://localhost:6969/add-data"
fetch(url, {
method: "POST",
headers: {
'Content-Type':'application/json',
'Accept': 'application/json'
},
//body: JSON.stringify(formData)
body: formData
})
// const result = response.json()
// console.log("Success:", result)
})
Flask后端:
@app.route("/add-data", methods=['POST'])
@cross_origin()
def add():
data=request.json
dateID=data.get('dateID')
week_day=data.get('week_day')
day=data.get('day')
rate=data.get('rate')
cursor = mysql.connection.cursor(MySQLdb.cursors.DictCursor)
sql_query="INSERT INTO years_2016_2025 (dateID, week_day, day, rate) VALUES (%s, %s, %s, %s)"
cursor.execute(sql_query, (dateID, week_day, day, rate))
mysql.connection().commit()
cursor.close()
return jsonify({"message": "Data saved successfully!"}, 201)
我已经尝试将表单数据输出到控制台,但结果为null;开发者工具的网络响应错误信息显示:“浏览器(或代理)发送了服务器无法理解的请求。”
解决方案
如果你想以 JSON 发送,那么你不能使用 formData,但
body: JSON.stringify({ dateID: dateID, week_day: weekDay, day: day, rate: rate }),
你可以在Mozilla文档中找到关于 fetch 的更多信息:Fetch API的使用
你也可以使用
body: JSON.stringify(Object.fromEntries(formData)),
就像在这个问题的回答中
javascript - How to convert FormData (HTML5 object) to JSON - Stack Overflow
如果你想要发送带有代码 201 的响应,那么它必须位于 jsonify 之外
它必须创建一个元组 data, code
return jsonify({"message": "Data saved successfully!"}), 201
Flask文档:关于响应
最小可运行的代码(不含数据库)单文件版,方便大家直接复制并测试。
from flask import Flask, request, jsonify
from flask_cors import CORS, cross_origin
from waitress import serve
PORT = 6969
html = """
<!DOCTYPE html>
<head>
<meta charset="utf-8">
</head>
<body>
<form id="form" method="POST">
<label> Date ID </label>
<input type="text" id="dateID" name="dateID">
<br>
<label> Day of the Week </label>
<input type="text" id="week_day" name="week_day">
<br>
<label> Day </label>
<input type="date" id="day" name="day">
<br>
<label> Rate </label>
<input type="text" id="rate" name="rate">
<br>
<input id="submit" type="submit">
</form>
<div id="message"></div>
<script>
const form = document.getElementById("form");
const message = document.getElementById("message");
form.addEventListener('submit', function(event) {
event.preventDefault();
const dateID = document.getElementById('dateID').value;
const weekDay = document.getElementById('week_day').value;
const day = document.getElementById('day').value;
const rate = document.getElementById('rate').value;
const formData = new FormData(form);
//const url = "http://localhost:6969/add-data";
const url = "/add-data"; // you can use URL without domain and port
fetch(url, {
method: "POST",
headers: {
'Content-Type':'application/json',
'Accept': 'application/json'
},
//body: formData // wrong: form body
//body: JSON.stringify(formData) // wrong: empty body
body: JSON.stringify(Object.fromEntries(formData)) // works
//body: JSON.stringify({dateID: dateID, week_day: weekDay, day: day, rate: rate}) // works
})
.then(response => response.json()) // TODO: use `if(!response.ok)` to catch errors 40x, 50x
.then(data => {
console.log("Success:", data.message);
message.innerHTML = data.message;
})
.catch(error => {
console.error("Error:", error);
message.innerHTML = error;
});
})
</script>
</body>
</html>"""
app = Flask(__name__)
CORS(app)
app.secret_key = ""
@app.route("/")
@cross_origin()
def index():
return html
@app.route("/add-data", methods=["POST"])
@cross_origin()
def add():
data = request.json
dateID = data.get("dateID")
week_day = data.get("week_day")
day = data.get("day")
rate = data.get("rate")
print(f"{data=}")
# cursor = mysql.connection.cursor(MySQLdb.cursors.DictCursor)
# sql_query="INSERT INTO years_2016_2025 (dateID, week_day, day, rate) VALUES (%s, %s, %s, %s)"
# cursor.execute(sql_query, (dateID, week_day, day, rate))
# mysql.connection().commit()
# cursor.close()
return jsonify({"message": "Data saved successfully!"}), 201
if __name__ == "__main__":
print(f"Running http://localhost:{PORT}")
# app.run("localhost", port=PORT, debug=True)
serve(app, host="0.0.0.0", port=PORT)
同时我添加了用于数据库的代码 sqlite(不需要安装服务器),
所以大家仍然可以直接复制并运行。
它会自动创建数据库文件。
我还添加了一个页面,用于显示数据库中所有数据的表。
它使用 render_template_string 与 {% for ... %}。
表格的链接在表单上方。
from flask import Flask, request, jsonify, render_template_string
from flask_cors import CORS, cross_origin
from waitress import serve
import sqlite3
PORT = 6969
html = """
<!DOCTYPE html>
<head>
<meta charset="utf-8">
</head>
<body>
<a href="/all">Table</a>
<hr>
<form id="form" method="POST">
<label> Date ID </label>
<input type="text" id="dateID" name="dateID">
<br>
<label> Day of the Week </label>
<input type="text" id="week_day" name="week_day">
<br>
<label> Day </label>
<input type="date" id="day" name="day">
<br>
<label> Rate </label>
<input type="text" id="rate" name="rate">
<br>
<input id="submit" type="submit">
</form>
<div id="message"></div>
<script>
const form = document.getElementById("form");
const message = document.getElementById("message");
form.addEventListener('submit', function(event) {
event.preventDefault();
const dateID = document.getElementById('dateID').value;
const weekDay = document.getElementById('week_day').value;
const day = document.getElementById('day').value;
const rate = document.getElementById('rate').value;
const formData = new FormData(form);
//const url = "http://localhost:6969/add-data";
const url = "/add-data"; // you can use URL without domain and port
fetch(url, {
method: "POST",
headers: {
'Content-Type':'application/json',
'Accept': 'application/json'
},
//body: formData // wrong: form body
//body: JSON.stringify(formData) // wrong: empty body
body: JSON.stringify(Object.fromEntries(formData)) // works
//body: JSON.stringify({dateID: dateID, week_day: weekDay, day: day, rate: rate}) // works
})
.then(response => response.json()) // TODO: use `if(!response.ok)` to catch errors 40x, 50x
.then(data => {
console.log("Success:", data.message);
message.innerHTML = data.message;
})
.catch(error => {
console.error("Error:", error);
message.innerHTML = error;
});
})
</script>
</body>
</html>"""
app = Flask(__name__)
CORS(app)
app.secret_key = ""
@app.route("/")
@cross_origin()
def index():
return html
@app.route("/add-data", methods=["POST"])
@cross_origin()
def add():
data = request.json
dateID = data.get("dateID")
week_day = data.get("week_day")
day = data.get("day")
rate = data.get("rate")
print(f"{data=}")
# mysql_insert(dateID, week_day, day, rate)
sqlite_insert(dateID, week_day, day, rate)
return jsonify({"message": "Data saved successfully!"}), 201
@app.route("/all")
def show_all():
data = sqlite_select_all()
return render_template_string(
"""
<style>
td {border: 1px solid black; padding: 5px 15px;}
</style>
<a href="/">Main</a>
<hr>
<table>
<tr><th>ID</th><th>Date ID</th><th>WeekDay</th><th>Day</th><th>Rate</th></tr>
{% for row in data %}
<tr>{% for item in row %}<td>{{ item }}</td>{% endfor %}<tr>
{% endfor %}
</table>
""",
data=data,
)
def mysql_insert(dateID, week_day, day, rate):
cursor = mysql.connection.cursor(MySQLdb.cursors.DictCursor)
sql_query = "INSERT INTO years_2016_2025 (dateID, week_day, day, rate) VALUES (%s, %s, %s, %s)"
cursor.execute(sql_query, (dateID, week_day, day, rate))
mysql.connection().commit()
cursor.close()
def sqlite_create():
# import sqlite3
query = """
CREATE TABLE IF NOT EXISTS years_2016_2025 (
id INTEGER PRIMARY KEY AUTOINCREMENT,
dateID TEXT,
week_day TEXT,
day TEXT,
rate TEXT
)
"""
conn = sqlite3.connect("database.db")
cursor = conn.cursor()
cursor.execute(query)
conn.commit()
conn.close()
print("Database created")
result = sqlite_select_all()
if not result:
print("empty database ... adding example rows")
sqlite_insert("today", "Sunday", "2026-05-31", "-1_000_000")
sqlite_insert("yesterday", "Saturday", "2026-05-30", "+1_000_000")
else:
print("database not empty")
def sqlite_insert(dateID, week_day, day, rate):
query = (
"INSERT INTO years_2016_2025 (dateID, week_day, day, rate) VALUES (?, ?, ?, ?)"
)
conn = sqlite3.connect("database.db")
cursor = conn.cursor()
result = cursor.execute(query, (dateID, week_day, day, rate))
result = result.fetchall()
conn.commit()
conn.close()
return result
def sqlite_select_all():
query = "SELECT * FROM years_2016_2025"
conn = sqlite3.connect("database.db")
cursor = conn.cursor()
result = cursor.execute(query)
result = result.fetchall()
conn.commit()
conn.close()
return result
if __name__ == "__main__":
sqlite_create() # you can remove after first execution (but if you keep it then it will not delete previous data)
print(f"Running http://localhost:{PORT}")
# app.run("localhost", port=PORT, debug=True)
serve(app, host="0.0.0.0", port=PORT)
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

