- 安装Flask-WTF
为了更搞笑的制作表单,需要安装一个flask的扩展包——flask-wtf。
pip install flask-wtf
- 配置块
在APP中,我们经常会用到一些秘钥之类的配置,秉承先前独立原则,把配置块直接独立出来,在等级目录中建立一个配置文件config.py。
另外为了防止Cross-Site Request Forgery(跨站点伪造请求),需要秘钥控制。
import os
class Config(object):
#environ表示环境变量,
#二次元操作:当系统有环境变量时就取名为SECRET_KEY的环境变量,否则赋值'you-will-never-guess'
SECRET_KEY = os.environ.get('SECRET_KEY') or 'you-will-never-guess'
有了独立的配置后,又怎么让flask认得呢?在app/init.py中导入模块:
from flask import Flask
from config import Config #导入刚才建立的Config模块
app = Flask(__name__)
app.config.from_object(Config) #第一个小写config是app的属性,第二个大写Config是导入模块
3、登录页面表单字段设置,独立的模块app/forms.py:
#flask的扩展库一般是以flask_**来命名
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField, SubmitField
from wtforms.validators import DataRequired
class LoginForm(FlaskForm):
#各字段第一个参数值表示的是字段显示名称,DataRequired()用来验证数据是否为空
username = StringField('Username', validators=[DataRequired()])
password = PasswordField('Password', validators=[DataRequired()])
remember_me = BooleanField('Remember Me')
submit = SubmitField('Sign In')
4、登录页面模板设置app/templates/login.html,引用刚才建立的LoginForm模块中字段:
{% extends "base.html" %}
{% block content %}
<h1>Sign In</h1>
<form action="" method="post" novalidate> #action表示向何处发送表单数据,为空代表当前地址
{{ form.hidden_tag() }} #生成一个隐藏的字段,防止CSRF攻击,一般同秘钥一起使用
<p>
{{ form.username.label }}<br>
{{ form.username(size=32) }} #size:输入字段的宽度
</p>
<p>
{{ form.password.label }}<br>
{{ form.password(size=32) }} #size:输入字段的宽度
</p>
<p>{{ form.remember_me() }} {{ form.remember_me.label }}</p>
<p>{{ form.submit() }}</p>
</form>
{% endblock %}
5、在app/routes.py中增加login的视图函数
from flask import render_template, flash, redirect
@app.route('/login', methods=['GET', 'POST']) #methods:访问请求方式
def login():
form = LoginForm()
if form.validate_on_submit(): #当浏览器传递的是Get方式时,validate_on_submit()返回False,如果Post方式时,所有字段如果验证通过方可返回True
flash('Login requested for user {}, remember_me={}'.format(
form.username.data, form.remember_me.data)) #flash生成一个提示闪现消息
return redirect('/index') # redirect:跳转页面
return render_template('login.html', title='Sign In', form=form)
6、在base.html中增添闪现信息,通过列表方式展示。
其中遇到一个坑:{%…%}语法,如果在%符号前后加入空格的话,网页访问的时候,后台程序会报错,提示‘}’错误。
<html>
<head>
{% if title %}
<title>{{ title }} - microblog</title>
{% else %}
<title>microblog</title>
{% endif %}
</head>
<body>
<div>
Microblog:
<a href="/index">Home</a>
<a href="/login">Login</a>
</div>
<hr>
{% with messages = get_flashed_messages() %} #获取所有的闪现消息,list方式存储
{% if messages %}
<ul>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
{% block content %}{% endblock %}
</body>
</html>
7、登录页面录入信息校验,提示录入错误信息,文件app/templates/login.html。
{% extends "base.html" %}
{% block content %}
<h1>Sign In</h1>
<form action="" method="post" novalidate>
{{ form.hidden_tag() }}
<p>
{{ form.username.label }}<br>
{{ form.username(size=32) }}<br>
{% for error in form.username.errors %} #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.remember_me() }} {{ form.remember_me.label }}</p>
<p>{{ form.submit() }}</p>
</form>
{% endblock %}
至此,运行flask后,最后的界面如下:
8、关于连接的探讨
在前边,我们共使用了两种连接方式。
其一:在导航栏模板中定义的导航项:
<div>
Microblog:
<a href="/index">Home</a>
<a href="/login">Login</a>
</div>
其二:在登录模板中使用的跳转操作:
@app.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
# ...
return redirect('/index')
# ...
这种方式直接写连接地址,会存在一个问题:如果后期需要修改连接地址的时候,你就需要查找到代码文件再修改,维护起来就困难。
Flask自带了一个很好的函数url_for()来处理此种问题.
url_for()使用url映射中保存的信息生成url。
url_for()的基本用法:
#通过视图函数映射
url_for(‘index’ name =’wang’,external=True) #第一个参数index是视图函数名,第二个参数自定义的参数(可以起到拼接的效果)。
#通过静态文件映射
url_for('static',filename='css/styles.css',_external=True) 得到的结果:http://localhost:5000/static/css/styles.css
上边两种连接方式的改进方式如下:
<div>
Microblog:
<a href="{{ url_for('index') }}">Home</a> #index是视图函数名称
<a href="{{ url_for('login') }}">Login</a> #login是视图函数名称
</div>
from flask import render_template, flash, redirect, url_for
# ...
@app.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
# ...
return redirect(url_for('index')) #index是视图函数名称
# ...