“Python Flask: 实现用户注册功能”的版本间的差异
(→includes/_formhelpers.html) |
(→表单文件forms.py) |
||
(未显示同一用户的15个中间版本) | |||
第5行: | 第5行: | ||
<nowiki> | <nowiki> | ||
+ | from flask import Flask, render_template, flash, redirect, url_for, session, request, logging | ||
+ | from mysql_util import MysqlUtil | ||
+ | from passlib.hash import sha256_crypt | ||
+ | |||
app = Flask(__name__) # 创建应用 | app = Flask(__name__) # 创建应用 | ||
第11行: | 第15行: | ||
def register(): | def register(): | ||
form = RegisterForm(request.form) # 实例化表单类 | form = RegisterForm(request.form) # 实例化表单类 | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
return render_template('register.html', form=form) # 渲染模板板 | return render_template('register.html', form=form) # 渲染模板板 | ||
第62行: | 第54行: | ||
===创建公共文件=== | ===创建公共文件=== | ||
====layout.html==== | ====layout.html==== | ||
− | + | 在templates目录下创建公共文件layout.html | |
<nowiki> | <nowiki> | ||
第86行: | 第78行: | ||
====includes/_navbar.html==== | ====includes/_navbar.html==== | ||
− | + | 在templates目录的下 创建子目录includes,并创建文件_navbar.html | |
<nowiki> | <nowiki> | ||
<nav class="navbar navbar-default"> | <nav class="navbar navbar-default"> | ||
第120行: | 第112行: | ||
====includes/_messages.html==== | ====includes/_messages.html==== | ||
+ | 在templates目录的子目录includes下,创建文件_messages.html | ||
<nowiki> | <nowiki> | ||
{% with messages = get_flashed_messages(with_categories=true) %} | {% with messages = get_flashed_messages(with_categories=true) %} | ||
第137行: | 第130行: | ||
{% endif %} | {% endif %} | ||
</nowiki> | </nowiki> | ||
+ | |||
====includes/_footer.html==== | ====includes/_footer.html==== | ||
+ | 在templates目录的子目录includes下,创建文件_footer.html | ||
+ | |||
<nowiki> | <nowiki> | ||
<!-- Footer --> | <!-- Footer --> | ||
第153行: | 第149行: | ||
====includes/_formhelpers.html==== | ====includes/_formhelpers.html==== | ||
− | + | 在templates目录的子目录includes下,创建文件_formhelpers.html | |
+ | |||
+ | 在该文件中定义了一个宏render_field | ||
+ | |||
<nowiki> | <nowiki> | ||
{% macro render_field(field) %} | {% macro render_field(field) %} | ||
第164行: | 第163行: | ||
{% endif %} | {% endif %} | ||
{% endmacro %}</nowiki> | {% endmacro %}</nowiki> | ||
+ | |||
+ | ==实现注册功能== | ||
+ | |||
+ | ===注册函数register()=== | ||
+ | 通过request.method 判断是否提交了表单, | ||
+ | |||
+ | 然后通过form.validate() 进行字段验证, | ||
+ | |||
+ | 获取信息,并加密, | ||
+ | |||
+ | 将信息写入数据库 | ||
+ | |||
+ | 跳转到登陆页面 并显示成功信息 | ||
+ | |||
+ | 如果注册失败,则显示注册信息。 | ||
+ | |||
+ | '''注意:新增from forms import RegisterForm,ArticleForm 一行应用''' | ||
+ | |||
+ | manage.py: | ||
+ | |||
+ | <nowiki> | ||
+ | from flask import Flask, render_template, flash, redirect, url_for, session, request, logging | ||
+ | from mysql_util import MysqlUtil | ||
+ | |||
+ | from passlib.hash import sha256_crypt | ||
+ | from forms import RegisterForm,ArticleForm | ||
+ | |||
+ | app = Flask(__name__) # 创建应用 | ||
+ | |||
+ | # 用户注册 | ||
+ | @app.route('/register', methods=['GET', 'POST']) | ||
+ | def register(): | ||
+ | form = RegisterForm(request.form) # 实例化表单类 | ||
+ | if request.method == 'POST' and form.validate(): # 如果提交表单,并字段验证通过 | ||
+ | # 获取字段内容 | ||
+ | email = form.email.data | ||
+ | username = form.username.data | ||
+ | password = sha256_crypt.encrypt(str(form.password.data)) # 对密码进行加密 | ||
+ | |||
+ | db = MysqlUtil() # 实例化数据库操作类 | ||
+ | sql = "INSERT INTO users(email,username,password) \ | ||
+ | VALUES ('%s', '%s', '%s')" % (email,username,password) # user表中插入记录 | ||
+ | db.insert(sql) | ||
+ | |||
+ | flash('您已注册成功,请先登录', 'success') # 闪存信息 | ||
+ | return redirect(url_for('login')) # 跳转到登录页面 | ||
+ | |||
+ | return render_template('register.html', form=form) # 渲染模板 | ||
+ | |||
+ | if __name__ == '__main__':#程序入口 | ||
+ | app.secret_key='secret123' | ||
+ | app.run()#让应用运行在本地服务器上。 | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | </nowiki> | ||
+ | |||
+ | |||
+ | flask提供了一个非常有用的flash()函数,它可以用来“闪现”需要提示给用户的消息,比如当用户登录成功后显示“欢迎回来!”。在视图函数调用flash()函数,传入消息内容,flash()函数把消息存储在session中,我们需要在模板中使用全局函数get_flashed_messages()获取消息并将它显示出来。 | ||
+ | |||
+ | 通过flash()函数发送的消息会存储在session对象中,所以我们需要为程序设置秘钥。可以通过app.secret_key属性或配置变量SECRET_KEY设置。 | ||
+ | |||
+ | 你可以在任意视图函数中调用flash()函数发送消息。 | ||
+ | |||
+ | ===(注册后跳转的)登录函数login=== | ||
+ | manage.py: | ||
+ | |||
+ | <nowiki> | ||
+ | @app.route('/login', methods=['GET', 'POST']) | ||
+ | def login(): | ||
+ | return '登录成功!' | ||
+ | </nowiki> | ||
+ | ===表单文件forms.py=== | ||
+ | |||
+ | forms.py | ||
+ | |||
+ | 与manage.py同一目录下 | ||
+ | |||
+ | 主要提供表单验证提示功能。 | ||
+ | |||
+ | <nowiki> | ||
+ | from wtforms import Form, StringField, TextAreaField, PasswordField | ||
+ | from wtforms.validators import DataRequired,Length,Email,EqualTo | ||
+ | |||
+ | # Article Form Class | ||
+ | class ArticleForm(Form): | ||
+ | title = StringField( | ||
+ | '标题', | ||
+ | validators=[ | ||
+ | # DataRequired(message= '标题长度应该在2-30字符之间'), | ||
+ | DataRequired(message='长度不少于5个字符'), | ||
+ | Length(min=2,max=30) | ||
+ | ] | ||
+ | ) | ||
+ | content = TextAreaField( | ||
+ | '内容', | ||
+ | validators=[ | ||
+ | DataRequired(message='长度不少于5个字符'), | ||
+ | Length(min=5) | ||
+ | ] | ||
+ | ) | ||
+ | |||
+ | # Register Form Class | ||
+ | class RegisterForm(Form): | ||
+ | username = StringField( | ||
+ | '用户名', | ||
+ | validators=[ | ||
+ | DataRequired(message='请输入用户名'), | ||
+ | Length(min=2, max=25,message='长度在2-25个字符之间') | ||
+ | ] | ||
+ | ) | ||
+ | email = StringField( | ||
+ | '邮箱', | ||
+ | validators = [ | ||
+ | DataRequired(message="请输入邮箱"), | ||
+ | Email(message='请输入正确的邮箱格式') | ||
+ | ] | ||
+ | ) | ||
+ | password = PasswordField( | ||
+ | '密码', | ||
+ | validators = [ | ||
+ | DataRequired(message='密码不能为空'), | ||
+ | Length(min=6,max=20,message='长度在6-20个字符之间'), | ||
+ | ] | ||
+ | ) | ||
+ | confirm = PasswordField( | ||
+ | '确认密码', | ||
+ | validators=[ | ||
+ | DataRequired(message='密码不能为空'), | ||
+ | Length(min=6, max=20), | ||
+ | EqualTo('password', message='2次输入密码不一致') | ||
+ | ] | ||
+ | ) | ||
+ | </nowiki> | ||
+ | |||
+ | ==效果图== | ||
+ | |||
+ | [[文件:python220116.png|600px]] | ||
+ | |||
+ | [[文件:python22012801.png|600px]] | ||
+ | |||
+ | 后台mysql验证: | ||
+ | |||
+ | mysql> use store; | ||
+ | |||
+ | Database changed | ||
+ | |||
+ | mysql> select * from users; | ||
+ | |||
+ | <nowiki>+----+----------------+-----------------+-------------------------------------------------------------------------------+ | ||
+ | | id | username | email | password | | ||
+ | +----+----------------+-----------------+-------------------------------------------------------------------------------+ | ||
+ | | 1 | maxin5@163.com | maxin5 | 123456 | | ||
+ | | 2 | xin | xin5452@163.com | 123456 | | ||
+ | | 3 | zhangsan | zhangsan@qq.com | $5$rounds=535000$NWzpyaQlfm04uD1B$jEpEwGya/i0x3kv5v9SOG7HYR51jtU4neI3ttMaL.cD | | ||
+ | | 4 | zhangsi | zhangsi@qq.com | $5$rounds=535000$SeeGpq.m7GtFTzum$K2ehl.G8WfgFsqQ2Xmq/omc7Q2pT3.9JYVcoofv4vq6 | | ||
+ | | 5 | wangfu | wangwu@qq.com | $5$rounds=535000$DsYcIFyS6jnFxPIw$ntFyQPCRkk60/ko7gaoQmh0revg8ElqyBp35JcdrH.6 | | ||
+ | | 6 | wangliu | wangliu@qq.com | $5$rounds=535000$o04yHm/Mqsefhips$XqlOeNxYP6sva39pb5sc6YnQavwCjC5fsJSFuNCDxO/ | | ||
+ | +----+----------------+-----------------+-------------------------------------------------------------------------------+ | ||
+ | 6 rows in set (0.03 sec) | ||
+ | </nowiki> |
2022年1月28日 (五) 07:44的最新版本
目录
创建注册路由
在manage.py入口文件中,创建一个名为app的Flask实例,
然后用app.route()函数创建路由。
from flask import Flask, render_template, flash, redirect, url_for, session, request, logging from mysql_util import MysqlUtil from passlib.hash import sha256_crypt app = Flask(__name__) # 创建应用 # 用户注册 @app.route('/register', methods=['GET', 'POST']) def register(): form = RegisterForm(request.form) # 实例化表单类 return render_template('register.html', form=form) # 渲染模板板
创建模板文件
创建模板文件
render_template()函数默认查找的模板文件路径"/templates",
在该路径下创建register.html
{% extends 'layout.html' %} {% block body %} <div class="content"> <h1 class="title-center">用户注册</h1> {% from "includes/_formhelpers.html" import render_field %} <form method="POST" action=""> <div class="form-group"> {{render_field(form.email, class_="form-control")}} </div> <div class="form-group"> {{render_field(form.username, class_="form-control")}} </div> <div class="form-group"> {{render_field(form.password, class_="form-control")}} </div> <div class="form-group"> {{render_field(form.confirm, class_="form-control")}} </div> <p><input type="submit" class="btn btn-primary" value="注册"></p> </form> </div> {% endblock %}
创建公共文件
layout.html
在templates目录下创建公共文件layout.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>读书笔记</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> <link rel="stylesheet" href="/static/css/style.css"> <script src="https://cdn.bootcss.com/jquery/2.2.4/jquery.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> </head> <body> {% include 'includes/_navbar.html' %} <div class="container"> {% include 'includes/_messages.html' %} {% block body %}{% endblock %} </div> {% include 'includes/_footer.html' %} </body> </html>
在templates目录的下 创建子目录includes,并创建文件_navbar.html
<nav class="navbar navbar-default"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="/">学习笔记</a> </div> <div id="navbar" class="collapse navbar-collapse"> <ul class="nav navbar-nav"> <li><a href="/">主页</a></li> <li><a href="/articles">笔记</a></li> <li><a href="/about">关于</a></li> </ul> <ul class="nav navbar-nav navbar-right"> {% if session.logged_in %} <li><a href="/dashboard">控制台</a></li> <li><a href="/logout">退出</a></li> {% else %} <li><a href="/register">注册</a></li> <li><a href="/login">登录</a></li> {% endif %} </ul> </div><!--/.nav-collapse --> </div> </nav>
includes/_messages.html
在templates目录的子目录includes下,创建文件_messages.html
{% with messages = get_flashed_messages(with_categories=true) %} {% if messages %} {% for category, message in messages %} <div class="alert alert-{{ category }}">{{ message }}</div> {% endfor %} {% endif %} {% endwith %} {% if error %} <div class="alert alert-danger">{{error}}</div> {% endif %} {% if msg %} <div class="alert alert-success">{{msg}}</div> {% endif %}
在templates目录的子目录includes下,创建文件_footer.html
<!-- Footer --> <footer class="page-footer font-small blue" style="margin-top: 50px"> <!-- Copyright --> <div class="footer-copyright text-center py-3"> Copyright ©2007-2019 <a href="http://www.mingrisoft.com">明日科技有限公司</a> All Rights Reserved 吉ICP备10002740号-2 吉公网安备22010202000132 </div> <!-- Copyright --> </footer> <!-- Footer -->
includes/_formhelpers.html
在templates目录的子目录includes下,创建文件_formhelpers.html
在该文件中定义了一个宏render_field
{% macro render_field(field) %} {{ field.label }} {{ field(**kwargs)|safe }} {% if field.errors %} {% for error in field.errors %} <span class="help-inline text-danger">{{ error }}</span> {% endfor %} {% endif %} {% endmacro %}
实现注册功能
注册函数register()
通过request.method 判断是否提交了表单,
然后通过form.validate() 进行字段验证,
获取信息,并加密,
将信息写入数据库
跳转到登陆页面 并显示成功信息
如果注册失败,则显示注册信息。
注意:新增from forms import RegisterForm,ArticleForm 一行应用
manage.py:
from flask import Flask, render_template, flash, redirect, url_for, session, request, logging from mysql_util import MysqlUtil from passlib.hash import sha256_crypt from forms import RegisterForm,ArticleForm app = Flask(__name__) # 创建应用 # 用户注册 @app.route('/register', methods=['GET', 'POST']) def register(): form = RegisterForm(request.form) # 实例化表单类 if request.method == 'POST' and form.validate(): # 如果提交表单,并字段验证通过 # 获取字段内容 email = form.email.data username = form.username.data password = sha256_crypt.encrypt(str(form.password.data)) # 对密码进行加密 db = MysqlUtil() # 实例化数据库操作类 sql = "INSERT INTO users(email,username,password) \ VALUES ('%s', '%s', '%s')" % (email,username,password) # user表中插入记录 db.insert(sql) flash('您已注册成功,请先登录', 'success') # 闪存信息 return redirect(url_for('login')) # 跳转到登录页面 return render_template('register.html', form=form) # 渲染模板 if __name__ == '__main__':#程序入口 app.secret_key='secret123' app.run()#让应用运行在本地服务器上。
flask提供了一个非常有用的flash()函数,它可以用来“闪现”需要提示给用户的消息,比如当用户登录成功后显示“欢迎回来!”。在视图函数调用flash()函数,传入消息内容,flash()函数把消息存储在session中,我们需要在模板中使用全局函数get_flashed_messages()获取消息并将它显示出来。
通过flash()函数发送的消息会存储在session对象中,所以我们需要为程序设置秘钥。可以通过app.secret_key属性或配置变量SECRET_KEY设置。
你可以在任意视图函数中调用flash()函数发送消息。
(注册后跳转的)登录函数login
manage.py:
@app.route('/login', methods=['GET', 'POST']) def login(): return '登录成功!'
表单文件forms.py
forms.py
与manage.py同一目录下
主要提供表单验证提示功能。
from wtforms import Form, StringField, TextAreaField, PasswordField from wtforms.validators import DataRequired,Length,Email,EqualTo # Article Form Class class ArticleForm(Form): title = StringField( '标题', validators=[ # DataRequired(message= '标题长度应该在2-30字符之间'), DataRequired(message='长度不少于5个字符'), Length(min=2,max=30) ] ) content = TextAreaField( '内容', validators=[ DataRequired(message='长度不少于5个字符'), Length(min=5) ] ) # Register Form Class class RegisterForm(Form): username = StringField( '用户名', validators=[ DataRequired(message='请输入用户名'), Length(min=2, max=25,message='长度在2-25个字符之间') ] ) email = StringField( '邮箱', validators = [ DataRequired(message="请输入邮箱"), Email(message='请输入正确的邮箱格式') ] ) password = PasswordField( '密码', validators = [ DataRequired(message='密码不能为空'), Length(min=6,max=20,message='长度在6-20个字符之间'), ] ) confirm = PasswordField( '确认密码', validators=[ DataRequired(message='密码不能为空'), Length(min=6, max=20), EqualTo('password', message='2次输入密码不一致') ] )
效果图
后台mysql验证:
mysql> use store;
Database changed
mysql> select * from users;
+----+----------------+-----------------+-------------------------------------------------------------------------------+ | id | username | email | password | +----+----------------+-----------------+-------------------------------------------------------------------------------+ | 1 | maxin5@163.com | maxin5 | 123456 | | 2 | xin | xin5452@163.com | 123456 | | 3 | zhangsan | zhangsan@qq.com | $5$rounds=535000$NWzpyaQlfm04uD1B$jEpEwGya/i0x3kv5v9SOG7HYR51jtU4neI3ttMaL.cD | | 4 | zhangsi | zhangsi@qq.com | $5$rounds=535000$SeeGpq.m7GtFTzum$K2ehl.G8WfgFsqQ2Xmq/omc7Q2pT3.9JYVcoofv4vq6 | | 5 | wangfu | wangwu@qq.com | $5$rounds=535000$DsYcIFyS6jnFxPIw$ntFyQPCRkk60/ko7gaoQmh0revg8ElqyBp35JcdrH.6 | | 6 | wangliu | wangliu@qq.com | $5$rounds=535000$o04yHm/Mqsefhips$XqlOeNxYP6sva39pb5sc6YnQavwCjC5fsJSFuNCDxO/ | +----+----------------+-----------------+-------------------------------------------------------------------------------+ 6 rows in set (0.03 sec)