在开始之前,先来看下项目的整体结构。
flask
├── app
│ ├── __init__.py
│ ├── routes.py
│ └── templates
│ ├── base.html
│ └── index.html
├── myblog.py
最终目录结构

flask_tutorial/
│
├── app/
│ ├── init.py
│ ├── routes.py
│ ├── forms.py
│ └── templates/
│ ├── base.html
│ ├── index.html
│ └── login.html
│
├── config.py
└── myblog.py
前面已经讲了一个简单的 hello world 和模板的应用, 但是在网页中这些肯定是不够用的,所以接下来讲一讲登录和注册都常用的表单。
首先安装 flask-wtf,这是表单的集成模块。
本节目标:实现:
-
表单模块
flask-wtf -
配置文件
config.py -
登录表单
forms.py -
登录页面
login.html -
登录路由
/login -
修改导航栏可点击"登录"
(venv) duke@coding:~/flask_tutorial/flask$ pip install flask-wtf
为了确保表单提交过来的是安全的,所以我们设定一个安全钥匙。当用户请求表单时,将这个钥匙给用户,然后用户提交表单的时候,将这个钥匙和我们服务器中的钥匙比对一下,如果安全的话就接收用户表单里的信息,如果比对不成功,那说明这个用户提交过来的数据有问题喽,拒绝他!
因此,咱们要设置一个这样的钥匙,但是接下也要设置数据库的位置和其他一些东西。想一想,这些需要配置的东西放到一个文件里,需要的话用一下多方便,因此要创建一个配置文件。
(venv) duke@coding:~/flask_tutorial/flask$ touch config.py
config.py : 配置信息
class Config(object):
#设置密匙要没有规律,别被人轻易猜到哦
SECRET_KEY = 'a9087FFJFF9nnvc2@#$%FSD'
钥匙设置好了,但是怎么使用呢?
app/_ _ init _ _.py : 使用配置文件 config.py 中的内容
from flask import Flask
#导入配置文件
from config import Config
app = Flask(__name__)
#添加配置信息
app.config.from_object(Config)
from app import routes
首先测试一下是否配置成功
(venv) duke@coding:~/flask_tutorial/flask$ python
Python 3.6.4 (default, May 3 2018, 19:35:55)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from myblog import app
>>> app.config['SECRET_KEY']
'a9087FFJFF9nnvc2@#$%FSD'
判断表格填写的是否正确,是否有未填写,格式是否有错误这些问题有集成好的方法供我们使用,我们只用写一个规定方法格式的文件即可。
新建一个 forms.py,用来处理表单信息。
(venv) duke@coding:~/flask_tutorial/flask$ touch app/forms.py
app/forms.py : 处理登录界面的信息.
from flask_wtf import FlaskForm
from wtforms import StringField,PasswordField,BooleanField,SubmitField
from wtforms.validators import DataRequired
class LoginForm(FlaskForm):
#DataRequired,当你在当前表格没有输入而直接到下一个表格时会提示你输入
username = StringField('用户名',validators=[DataRequired(message='请输入名户名')])
password = PasswordField('密码',validators=[DataRequired(message='请输入密码')])
remember_me = BooleanField('记住我')
submit = SubmitField('登录')
处理登录界面表单的文件写好了,那么现在当然就是要写一个登录界面啦。
在模板 templates 文件夹中创建 login.html
(venv) duke@coding:~/flask_tutorial/flask$ touch app/templates/login.html
app/templates/login.html : 完成登录模板
{% extends 'base.html' %}
{% block content %}
<h1>登 录</h1>
<form action="" method="post">
#用来实现在配置中激活的csrf保护
{{ form.hidden_tag() }}
<p>
{{ form.username.label }}<br>
{{ form.username(size=32) }}
</p>
<p>
{{ form.password.label }}<br>
{{ form.password(size=32) }}
</p>
<p>{{ form.remember_me() }} {{ form.remember_me.label }}</p>
<p>{{ form.submit() }}</p>
</form>
{% endblock %}
模板建立完成,接下来要对试图函数进行修改。
app/routes.py : 创建一个表单实例
from flask import render_template
from app import app
#导入表单处理方法
from app.forms import LoginForm
#前面的就不列举出来了,接着前面的写就可以了
#.......
@app.route('/login')
def login():
#创建一个表单实例
form = LoginForm()
return render_template('login.html',title='登 录',form=form)
对模板中的基类进行一个修改,因为上面跳转只有到首页的,添加一个跳转至登录界面的。
app/templates/base.html : 修改基类模板导航栏
<body>
<div>博客 :
<a href="/index">首页</a>
<a href="/login">登录</a>
</div>
{% block content %}
{% endblock %}
</body>
好的,现在先访问一下试试看,但是现在还不能登录哦。因为处理登录数据的部分还没有写,现在只是测试一下页面是否正确。

OK,看起来还不错,那接下来就来完成处理登录数据的部分。我在这里会用到闪现来传递信息,重定向来返回页面。
app/routes.py :处理表单数据
from flask import render_template,flash,redirect
from app import app
from app.forms import LoginForm
#前面的就不列举出来了,接着前面的写就可以了
#.......
@app.route('/login',methods=['GET','POST'])
def login():
form = LoginForm()
#验证表格中的数据格式是否正确
if form.validate_on_submit():
#闪现的信息会出现在页面,当然在页面上要设置
flash('用户登录的名户名是:{} , 是否记住我:{}'.format(
form.username.data,form.remember_me.data))
#重定向至首页
return redirect('/index')
#首次登录/数据格式错误都会是在登录界面
return render_template('login.html',title='登录',form=form)
既然有需要闪现的信息,那么页面模板就要随之修改。
app/templates/base.html : 添加需要闪现的界面格式。
<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
{% if title %}
<title>{{ title }} - 博客</title>
{% else %}
<title>欢迎来到博客!</title>
{% endif %}
</head>
<body>
<div>博客 :
<a href="/index">首页</a>
<a href="/login">登录</a>
</div>
<hr>
{% with messages = get_flashed_messages() %}
{% if messages %}
<ur>
{% for message in messages %}
<li>{{ message }}</li>>
{% endfor %}
</ur>
{% endif %}
{% endwith %}
{% block content %} {% endblock %}
</body>
</html>
登录界面不是很完善,因为哪里出错了没有显示在页面上呀,用户看不到,所以要完善登录页面。
app/templates/login.html : 完善显示信息
{% extends 'base.html' %}
{% block content %}
<h1>登 录</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.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 %}

运行一遍,可以看到结果很好。但是在成功的喜悦当中又有着些许遗憾,为啥?如果方法上的路由发生了变化,那么模板上的链接就失效了呀,为了解决这个问题,可以使用 url_for。这是根据视图函数名返回 url,就不用担心这个问题了。
app/templates/base.html : 修改模板中的基类的导航栏
<div>博客 :
<a href="{{ url_for('index') }}">首页</a>
<a href="{{ url_for('login') }}">登录</a>
</div>
既然模板中进行了修改,那么视图函数中肯定要进行修改。
app/routes.py : 添加 url_for
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'))
#.............

运行测试一下,会发现...... 很流畅!
最终效果:
