使用Python Flask向Cloud Firestore添加新用户的异常问题排查
Flask注册页面问题排查与修复
问题现象
- 提交合法邮箱密码后,Cloud Firestore未新增用户,页面直接跳转到首页
/而非/my_account - 提交非法邮箱或密码时,页面无刷新也无flash提示
- 已确认数据库读写权限正常
用户提供的原始代码
Python代码
# import flask package, firebase_admin for database ops from flask import Flask, session, render_template, request, redirect, url_for, flash import firebase_admin from firebase_admin import credentials from firebase_admin import firestore ### create app object using flask app = Flask(__name__) config = { "apiKey": "[]", "authDomain": "[]", "projectId": "[]", "storageBucket": "[]", "messagingSenderId": "[]", "appId": "[]", "measurementId": "[]", "databaseURL": "[website url]" } ### secret key (auto-generated) app.secret_key = '[secretkey]' ### initialize firestore database cred = credentials.Certificate("[pathtoprivatekey].json") firebase_admin.initialize_app(cred) db = firestore.client() ### create new users @app.route('/create_acct', methods=['POST', 'GET']) def create_user(email: str, password: str): if request.method == 'POST': email = request.form['email'] password = request.form['password'] data_to_push = {'email': email, 'password': password} if password=='' or email=='': flash('Please enter a password at least 7 characters long, containing at least two numbers, four letters, and one special character.') return redirect(url_for('create_acct')) else: if len(password)<7: flash('Please enter a password at least 7 characters long, containing at least two numbers, four letters, and one special character.') return redirect(url_for('create_acct')) else: # count numeric characters in password dig_count = 0 alpha_count = 0 for i in range(0,len(password)+1): if password[i].isdigit()==True: dig_count = dig_count+1 if password[i].isalpha()==True: alpha_count = alpha_count+1 if dig_count<2: flash('Please enter a password at least 7 characters long, containing at least two numbers, four letters, and one special character.') return redirect(url_for('create_acct')) elif alpha_count<4: flash('Please enter a password at least 7 characters long, containing at least two numbers, four letters, and one special character.') return redirect(url_for('create_acct')) elif password.isalnum() == True: flash('Please enter a password at least 7 characters long, containing at least two numbers, four letters, and one special character.') return redirect(url_for('create_acct')) else: # db.child('users').push(data_to_push) db.collection('users').document().set(data_to_push) return redirect(url_for('my_account')) return render_template('index.html')
HTML模板
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <link rel="stylesheet" href="static/style.css" /> <title>Create an account</title> </head> <body> <div class="toplinks"> <a href="/" class="button">Home</a> <a href="/my_account" class="button">My Account</a> <a href="/about" class="button">How It Works</a> <a href="/news" class="button">In the News</a> </div> {% for message in get_flashed_messages() %} <h2>{{ message }}</h2> {% endfor %} <div class="container"> <form action="/" method="POST"> <h2>Log in or create an account</h2> <div class="form-group"> <h3>Email</h3> <input type="text" name="email" id="email" placeholder="Email@domain" > </div> <div class="form-group"> <h3>Password</h3> <input type="text" name="password" id="password" placeholder="************" > </div> <input type="submit"> </form> </div> </body> </html>
核心问题与修复步骤
1. 表单提交路径错误
HTML表单的action设为/,导致提交请求直接发到首页路由,完全绕过了注册逻辑。
修复:将表单action改为/create_acct,或留空(默认提交到当前页面路径):
<form action="/create_acct" method="POST"> <!-- 更简洁的写法 --> <form method="POST">
2. 视图函数参数错误
create_user函数定义了email: str, password: str参数,但Flask视图函数不需要手动传入这些参数(请求参数通过request.form获取),会导致路由调用时参数缺失触发内部错误。
修复:移除函数定义中的多余参数:
@app.route('/create_acct', methods=['POST', 'GET']) def create_user(): # 移除email和password参数
3. 密码循环索引越界
循环for i in range(0,len(password)+1)会访问超出字符串长度的索引(Python字符串索引范围是0到len(password)-1),触发IndexError导致后续代码终止。
修复:修改循环范围,或直接遍历字符:
# 方案1:修正索引范围 for i in range(len(password)): # 方案2:更Pythonic的写法 for char in password: if char.isdigit(): dig_count += 1 if char.isalpha(): alpha_count += 1
4. 模板渲染错误
注册页面渲染了首页的index.html,可能导致页面逻辑混淆,且无法正确展示flash提示。
修复:返回对应的注册模板(比如create_acct.html):
return render_template('create_acct.html')
5. 密码输入类型错误
密码输入框用type="text"会明文显示密码,且不符合用户习惯。
修复:改为type="password":
<input type="password" name="password" id="password" placeholder="************" >
修复后的完整代码示例
Python代码
from flask import Flask, render_template, request, redirect, url_for, flash import firebase_admin from firebase_admin import credentials from firebase_admin import firestore app = Flask(__name__) app.secret_key = '[secretkey]' # 初始化Firebase cred = credentials.Certificate("[pathtoprivatekey].json") firebase_admin.initialize_app(cred) db = firestore.client() @app.route('/create_acct', methods=['POST', 'GET']) def create_user(): if request.method == 'POST': email = request.form.get('email', '').strip() password = request.form.get('password', '').strip() data_to_push = {'email': email, 'password': password} error_msg = '请输入至少7位的密码,包含至少2个数字、4个字母和1个特殊字符。' # 输入验证 if not email or not password: flash(error_msg) return redirect(url_for('create_user')) if len(password) < 7: flash(error_msg) return redirect(url_for('create_user')) dig_count = 0 alpha_count = 0 for char in password: if char.isdigit(): dig_count += 1 elif char.isalpha(): alpha_count += 1 if dig_count < 2 or alpha_count < 4 or password.isalnum(): flash(error_msg) return redirect(url_for('create_user')) # 写入Firestore try: db.collection('users').document().set(data_to_push) return redirect(url_for('my_account')) except Exception as e: flash(f'注册失败:{str(e)}') return redirect(url_for('create_user')) return render_template('create_acct.html') # 确保/my_account路由存在 @app.route('/my_account') def my_account(): return render_template('my_account.html') if __name__ == '__main__': app.run(debug=True)
HTML模板(create_acct.html)
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <link rel="stylesheet" href="static/style.css" /> <title>创建账户</title> </head> <body> <div class="toplinks"> <a href="/" class="button">首页</a> <a href="/my_account" class="button">我的账户</a> <a href="/about" class="button">使用说明</a> <a href="/news" class="button">最新动态</a> </div> {% for message in get_flashed_messages() %} <h2>{{ message }}</h2> {% endfor %} <div class="container"> <form method="POST"> <h2>登录或创建账户</h2> <div class="form-group"> <h3>邮箱</h3> <input type="email" name="email" id="email" placeholder="Email@domain" required > </div> <div class="form-group"> <h3>密码</h3> <input type="password" name="password" id="password" placeholder="************" required > </div> <input type="submit" value="创建账户"> </form> </div> </body> </html>
内容的提问来源于stack exchange,提问作者Quod fors feret
相关产品推荐
相关产品推荐

