用户注册
本章要构建的最后一项功能是注册表单,以便用户可以通过 Web 表单进行注册。 让我们在 app/forms.py 中创建 Web 表单类来开始吧:
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField, SubmitField
from wtforms.validators import ValidationError, DataRequired, Email, EqualTo
from app.models import User
# ...
class RegistrationForm(FlaskForm):
username = StringField('Username', validators=[DataRequired()])
email = StringField('Email', validators=[DataRequired(), Email()])
password = PasswordField('Password', validators=[DataRequired()])
password2 = PasswordField(
'Repeat Password', validators=[DataRequired(), EqualTo('password')])
submit = SubmitField('Register')
def validate_username(self, username):
user = User.query.filter_by(username=username.data).first()
if user is not None:
raise ValidationError('Please use a different username.')
def validate_email(self, email):
user = User.query.filter_by(email=email.data).first()
if user is not None:
raise ValidationError('Please use a different email address.')
代码中与验证相关的几处相当有趣。首先,对于 email
字段,我在 DataRequired
之后添加了第二个验证器,名为 Email
。 这个来自 WTForms 的另一个验证器将确保用户在此字段中键入的内容与电子邮件地址的结构相匹配。
由于这是一个注册表单,习惯上要求用户输入密码两次,以减少输入错误的风险。 出于这个原因,我提供了 password
和 password2
字段。 第二个 password 字段使用另一个名为 EqualTo
的验证器,它将确保其值与第一个 password 字段的值相同。
我还为这个类添加了两个方法,名为 validate_username()
和 validate_email()
。 当添加任何匹配模式 validate_ <field_name>
的方法时,WTForms 将这些方法作为自定义验证器,并在已设置验证器之后调用它们。 本处,我想确保用户输入的 username 和 email 不会与数据库中已存在的数据冲突,所以这两个方法执行数据库查询,并期望结果集为空。 否则,则通过 ValidationError
触发验证错误。 异常中作为参数的消息将会在对应字段旁边显示,以供用户查看。
我需要一个 HTML 模板以便在网页上显示这个表单,我其存储在 app/templates/register.html 文件中。 这个模板的构造与登录表单类似:
{% extends "base.html" %}
{% block content %}
<h1>Register</h1>
<form action="" method="post">
{{ form.hidden_tag() }}
<p>
{{ form.username.label }}<br>
{{ form.username(size=32) }}<br>
{% for error in form.username.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>
{{ form.email.label }}<br>
{{ form.email(size=64) }}<br>
{% for error in form.email.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>
{{ form.password.label }}<br>
{{ form.password(size=32) }}<br>
{% for error in form.password.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>
{{ form.password2.label }}<br>
{{ form.password2(size=32) }}<br>
{% for error in form.password2.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>{{ form.submit() }}</p>
</form>
{% endblock %}
登录表单模板需要在其表单之下添加一个链接来将未注册的用户引导到注册页面:
<p>New User? <a href="{{ url_for('register') }}">Click to Register!</a></p>
最后,我来实现处理用户注册的视图函数,存储在 app/routes.py 中,代码如下:
from app import db
from app.forms import RegistrationForm
# ...
@app.route('/register', methods=['GET', 'POST'])
def register():
if current_user.is_authenticated:
return redirect(url_for('index'))
form = RegistrationForm()
if form.validate_on_submit():
user = User(username=form.username.data, email=form.email.data)
user.set_password(form.password.data)
db.session.add(user)
db.session.commit()
flash('Congratulations, you are now a registered user!')
return redirect(url_for('login'))
return render_template('register.html', title='Register', form=form)
这个视图函数的逻辑也是一目了然,我首先确保调用这个路由的用户没有登录。表单的处理方式和登录的方式一样。在 if validate_on_submit()
条件块下,完成的逻辑如下:使用获取自表单的 username、email 和 password 创建一个新用户,将其写入数据库,然后重定向到登录页面以便用户登录。
精雕细琢之后,用户已经能够在此应用上注册帐户,并进行登录和注销。 请确保你尝试了我在注册表单中添加的所有验证功能,以便更好地了解其工作原理。 我将在未来的章节中再次更新用户认证子系统,以增加额外的功能,比如允许用户在忘记密码的情况下重置密码。 不过对于目前的应用来讲,这已经无碍于继续构建了。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论