flask学习(3)表单

一:配置

为了处理表单我们使用Flask-WTF插件,里面包含一些表单的创建和验证,csrf的保护.但在这之前我们要进行一波配置. 我们在microblog目录下创建一个配置文件(config.py)

1
2
CSRF_ENABLED = True
SECRET_KEY = 'you-will-never-guess'

配置好了之后,我们要让Flask来读取使用,所以我们要在flask应用程序被创建后去app的init.py里面进行修改

1
2
3
4
from flask import Flask
app = Flask(__name__)
app.config.from_object('config')
from app import views

其中app.config.from_object里面的参数是在app的上级目录下的配置文件

二:用户登录表单

这里使用openid进行登录 什么是openid呢?这是一个用于身份认证的一个东西,它的原理是

  1. 你首先得拥有一个合法的OpenID帐号,也就是说需要在一个验证服务器申请了一个帐号。

  2. 你有了这个帐号之后,就可以在任何一个其他支持OpenID验证的网站,并且用你上面申请的OpenID进行登录

  3. 因为这个网站并不知道你的身份是否正确,所以它会请求你的验证服务器对你的身份进行验证。

  4. 验证服务器告诉网站说,你是合法用户

  5. 网站接受你的身份,让你进入。

下面开始写第一个表单文件(app/forms.py)

1
2
3
4
5
6
7
from flask.ext.wtf import Form
from wtforms import StringField, BooleanField
from wtforms.validators import DataRequired

class LoginForm(Form):
openid = StringField('openid', validators=[DataRequired()])
remember_me = BooleanField('remember_me', default=False)

在这里写完了LoginForm之后,在views里面导入一下,实例化一下,然后传给模版里面就可以直接生成表单.

三:表单视图

直接在views里面改就好了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from flask import render_template,flash,redirect
from app import app
from .forms import LoginForm

@app.route('/')
@app.route('/index')
def index():
user = {'nickname':'Miguel'}
posts = [{'author':{"nickname":'John'},'body':'Beautiful day in Portland!'},{'author':{'nickname':'Susan'},'body':'The Avengers movie was so cool!'}]
return render_template("index.html",title = "Home!",user=user,posts=posts)

@app.route('/login',methods = ['GET','POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
flash('Login requested for OpenID="' + form.openid.data+'",remember_me='+str(form.remember_me.data))
return redirect('/index')
return render_template('login.html',title='Sign In',form=form,providers=app.config['OPENID_PROVIDERS'])

其实也就是导入一个LoginForm然后实例化传入模版 这里注意路由装饰器的methods参数,里面写["GET","POST"]就是这个视图接受get和post请求 如果不带的话是默认接受get请求 validate_on_submit 做了所有的表单处理 在表单展示的时候它返回false 在提交请求的时候它会收集数据然后验证,全部通过的话返回true否则返回false flash 这个函数的作用是快速地返回给用户页面上的一个消息. 这个函数在生产服务器的时候可以用来提供反馈给用户有关的行动 当然这个函数要是要返回给用户的话必须要在模版里面加上一些东西 比如

1
2
3
4
5
6
7
8
9
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul class=flashes>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}

错误处理 当用户验证失败的时候我们希望可以返回错误的信息,比如

1
2
3
{% for error in form.openid.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}<br>

四:改表单模版

模版先继承前面的base.html,然后我们再接受传入的form参数进行布局

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
{% extends "base.html" %}

{% block content %}
<script type="text/javascript">
function set_openid(openid,pr)
{
u = openid.search("<username>")
if (u != -1)
{
user = prompt('Enter your'+pr+' username:')
openid = openid.substr(0,u)+user
}
form = document.forms['login'];
form.elements['openid'].value = openid
}
</script>
<h1>Sign In</h1>
<form action="" method="post" name="login">
{{form.hidden_tag()}}
<p>
Please enter your OpenID:<br>
{{form.openid(size=80)}}<br>
{% for error in form.openid.errors %}
<span style="color:red;">[{{error}}]</span>
{% endfor %}<br>
{% for pr in providers %}
<a href="javascript:set_openid('{{ pr.url }}','{{ pr.name }}');">{{ pr.name }}</a>
{% endfor %}
</p>
<p>{{form.remember_me}}Remember Me</p>
<p><input type="submit" value="Login In!"></p>
</form>
{% endblock %}

其中的form.hidden_tag()会在服务器的返回页面加一段隐藏表单用于验证csrf 还比如像form.field_name里面可以带参数,比如这里要求openid宽度为80

五:处理openids

首先我们得定义一个openids的列表

1
2
3
4
5
6
7
8
9
CSRF_ENABLED = True
SECRET_KEY = 'you-will-never-guess'

OPENID_PROVIDERS = [
{ 'name': 'Google', 'url': 'https://www.google.com/accounts/o8/id' },
{ 'name': 'Yahoo', 'url': 'https://me.yahoo.com' },
{ 'name': 'AOL', 'url': 'http://openid.aol.com/<username>' },
{ 'name': 'Flickr', 'url': 'http://www.flickr.com/<username>' },
{ 'name': 'MyOpenID', 'url': 'https://www.myopenid.com' }]

然后在视图函数里面在加上一个providers=app.config["OPENID_PROVIDERS"],然后按照上面模版里面写的来写就ok了.