
本教程详细介绍了如何在 flask 应用中实现用户注册功能,重点解决 html 表单提交与 flask 路由不匹配导致的 404 错误。我们将深入探讨 flask 路由定义、html 表单 `action` 属性的正确配置、后端数据处理(包括密码哈希和数据库操作),以及前端表单验证。通过优化代码结构和引入安全最佳实践,确保用户注册流程的流畅与安全。
在构建 Web 应用时,前端(HTML)与后端(Flask)之间的通信是核心。当用户在网页上填写表单并点击提交时,浏览器会向服务器发送一个请求。这个请求的目标地址由 HTML 表单的 action 属性决定,而服务器端则通过 Flask 的路由(@app.route 装饰器)来匹配并处理这个请求。
一个常见的错误是 action 属性中指定的 URL 与 Flask 应用中定义的路由不一致,这会导致服务器返回 404 Not Found 错误。例如,如果 HTML 表单提交到 /sign_in,但 Flask 应用只定义了 /register 路由,那么服务器将无法找到对应的处理函数。
Flask 应用负责接收前端提交的数据,进行验证、处理,并最终存储到数据库中。
注册功能通常涉及显示注册表单(GET 请求)和处理表单提交(POST 请求)。
from flask import Flask, render_template, request
import hashlib
import psycopg2
app = Flask(__name__)
# 数据库连接配置
DB_CONFIG = {
"host": "localhost",
"port": "5432",
"dbname": "register_dc",
"user": "postgres",
"password": "=5.k7wT=!D" # 生产环境中不应硬编码密码
}
@app.route("/")
def show_registration_form():
"""显示用户注册表单页面"""
message = "Python and Postgres Registration Application"
return render_template("register.html", message=message)
@app.route("/register", methods=["GET", "POST"])
def register_user():
"""处理用户注册请求"""
if request.method == "POST":
t_email = request.form.get("t_email", "").strip()
t_password = request.form.get("t_password", "").strip()
# 2.2 数据校验
if not t_email:
return render_template("register.html", message="请输入您的邮箱地址")
if not t_password:
return render_template("register.html", message="请输入您的密码")
# 2.3 密码哈希处理
# 生产环境中应使用更安全的哈希算法,如 bcrypt,并加入盐值
t_hashed_password = hashlib.sha256(t_password.encode('utf-8')).hexdigest()
# 2.4 数据库插入操作
conn = None
cursor = None
try:
conn = psycopg2.connect(**DB_CONFIG)
cursor = conn.cursor()
# 使用参数化查询防止 SQL 注入
insert_sql = "INSERT INTO public.users (t_email, t_password) VALUES (%s, %s)"
cursor.execute(insert_sql, (t_email, t_hashed_password))
conn.commit()
message = "您的用户账户已成功添加。"
except psycopg2.Error as e:
conn.rollback() # 发生错误时回滚事务
message = f"数据库错误: {e}"
finally:
if cursor:
cursor.close()
if conn:
conn.close()
return render_template("register.html", message=message)
# 如果是 GET 请求,则显示表单(通常由 / 路由处理,但此路由也可以处理)
return render_template("register.html", message="请填写注册信息")
if __name__ == "__main__":
app.run(debug=True)使用 request.form.get("field_name", "") 可以安全地获取表单字段的值。get() 方法在字段不存在时会返回默认值(这里是空字符串),避免 KeyError。.strip() 方法可以去除用户输入两端的空白字符。
在将数据存入数据库前,必须进行服务器端校验,以确保数据的完整性和安全性。
前端表单负责收集用户输入,并将其发送到后端。
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>用户注册</title>
<style>
.container { width: 300px; margin: 50px auto; padding: 20px; border: 1px solid #ccc; border-radius: 5px; }
.form-row { margin-bottom: 15px; }
.form-row label { display: block; margin-bottom: 5px; }
.form-row input[type="text"] { width: 100%; padding: 8px; box-sizing: border-box; }
.form-row input[type="submit"] { width: 100%; padding: 10px; background-color: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer; }
.form-row input[type="submit"]:hover { background-color: #0056b3; }
.message { color: green; text-align: center; margin-bottom: 15px; }
.error-message { color: red; text-align: center; margin-bottom: 15px; }
</style>
<script language="JavaScript" type="text/javascript">
function checkform(form) {
function isEmpty(fieldValue, fieldName) {
if (fieldValue.trim() === "") {
alert("请输入 " + fieldName);
return true;
}
return false;
}
function charCheck(fieldValue) {
// 允许字母、数字、@、-、_、.
var validchars = '@-_.0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
for (var i = 0; i < fieldValue.length; i++) {
if (validchars.indexOf(fieldValue.charAt(i)) === -1) {
alert("请在该字段中使用字母、数字或特殊字符 (@ - _ .)");
return false;
}
}
return true;
}
// 客户端校验
if (isEmpty(form.t_email.value, "您的邮箱地址")) {
form.t_email.focus();
return false;
}
if (isEmpty(form.t_password.value, "您的密码")) {
form.t_password.focus();
return false;
}
if (!charCheck(form.t_email.value)) {
form.t_email.focus();
return false;
}
if (!charCheck(form.t_password.value)) {
form.t_password.focus();
return false;
}
return true; // 所有校验通过,允许表单提交
}
</script>
</head>
<body>
<div class='container'>
<!-- 显示后端传递的消息 -->
{% if message %}
{% if "错误" in message or "Please" in message %}
<p class="error-message">{{ message }}</p>
{% else %}
<p class="message">{{ message }}</p>
{% endif %}
{% endif %}
<form id='frmRegister' name='frmRegister' action='/register' method='post' onsubmit='return checkform(this);'>
<div class="form-row">
<label for="t_email">邮箱地址:</label>
<input type="text" id="t_email" name="t_email">
</div>
<div class="form-row">
<label for="t_password">密码:</label>
<input type="text" id="t_password" name="t_password">
</div>
<div class="form-row">
<input type="submit" id="btn_submit_register" value='注册'>
</div>
</form>
</div>
</body>
</html>客户端校验(通过 JavaScript)可以提升用户体验,在数据发送到服务器之前捕获简单的输入错误。
通过本教程,我们深入探讨了 Flask 应用中用户注册功能的实现细节,从前端表单的正确配置到后端的数据处理和数据库交互。核心在于确保 HTML 表单的 action 属性与 Flask 路由的精确匹配,同时强调了服务器端数据校验、密码安全哈希以及参数化查询等安全最佳实践。遵循这些指导原则,可以构建一个健壮、安全且用户友好的注册系统。
以上就是Flask 应用中用户注册功能的正确路由与表单提交实践的详细内容,更多请关注php中文网其它相关文章!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号