python flask学习(3)
这次主要学习web表单。学了下,很像是Django的form表单验证。不过有许多的不同。可以说是功能更加碎块化。Django的验证方式是很固定和严谨的,风格完全不同。
尽管Flask的请求对象提供的对象足够用于处理Web表单(如:request.form能获取POST请求中提交的表单数据),但有些任务很单调,而且要重复操作。比如生成表单的HTML代码和验证提交的表单数据。
Flask-WTF(http://pythonhosted.org/Flask-WTF)扩展可以把处理Web表单的过程编程一种愉快的体验。这个扩展对独立的WTForms(http://wtforms.simplecodes.com)包进行了包装,方便集成到Flask程序中。
1.跨站请求伪造保护
默认情况下,Flask-WTF能保护所有表单面免受跨站请求伪造(Cross-Site Request Forgery,CSRF)的攻击。恶意网站把请求发送到被攻击者已登录的其他网站是就会引发CSRF攻击。
为了实现CSRF保护,Flask-WTF需要程序设置一个密钥。Flask-WTF使用这个密钥生成加密令牌,再用令牌验证请求中表单数据的真伪。
这里也像是Django的CSRF防护。不过Django中是在POST表单提交中加入 {% csrf_token %}
<form method="POST" action="/post-url/">
{% csrf_token %} <input name='alex' value="xxx">
</form>
还有其ajax调用方式。不过这里不赘述。
flaskCSRF防护设置方式
app = Flask(__name__)
app.config['SECRET_KEY'] = '这里设置密钥'
注意:为了增强安全性,密钥不应该直接写入代码,而要保存在环境变量中。
2.表单类
index.html文件:
<html>
<head>
<title>首页</title>
</head>
<body>
{% if name %}
<h1>Hello,{{ name }}!</h1>
{% else %}
<h1>Hello Stranger!</h1>
{% endif %} <form method="POST">
{{ form.hidden_tag() }}
{{ form.name.label }} {{ form.name() }}
{{ form.submit() }}
</form>
</body>
</html>
app.py 文件:
from flask import Flask,render_template
from flask.ext.wtf import Form
from flask.ext.bootstrap import Bootstrap
from wtforms import StringField,SubmitField
from wtforms.validators import Required class NameForm(Form):
name = StringField('你的名字?',validators=[Required()])
submit = SubmitField('提交') app = Flask(__name__)
app.config['SECRET_KEY'] = 'ni cai'
bootstrap = Bootstrap(app) @app.route('/',methods=['GET','POST'])
def index():
name = None
nameForm = NameForm() if nameForm.validate_on_submit():
name = nameForm.name.data
nameForm.name.data = '' return render_template('index.html',form=nameForm,name=name) if __name__ == '__main__':
app.run(debug=True)
注意:
0.NameForm类,声明了一个输入姓名文本框和提交按钮。字段构造函数第一个参数吧表单渲染成HTML时使用的标号。其中输入姓名的文本框需要必须填写。
1.app.route修饰器中添加的methods参数告诉Flask在URL映射中把这个视图函数注册为GET和POST请求的处理程序,如果没有指定methods参数,就只把视图函数注册为GET请求处理程序。因为Web表单提交为POST方式,故需要显示标明。
2.nameForm.validate_on_submit()
方法,提交表单后,如果数据被所有验证函数接受,那么nameForm.validate_on_submit()
方法返回True,否则返回False。
index.html文件:
{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %} {% block title %}首页 {% endblock %} {% block page_content %} <div class="page-header">
{% if name %}
<h1> Hello,{{ name }}! </h1>
{% else %}
<h1>Hello,Stranger!</h1>
{% endif %}
</div> {{ wtf.quick_form(form) }} {% endblock %}
注意:
1.wtf.quick_form()
函数的参数为Flask-WTF表单对象,使用Bootstrap默认样式渲染传入的表单
重定向和用户会话
为何别让web程序把post请求作为浏览器发送的最后一个请求?
因用户在刷新页面后会再次提交表单,这样不仅用户体验下降,而且会加重服务器压力。解决办法是使用重定向作为POST请求的响应,而非常规响应。
但这种方法的问题是,程序处理完POST请求时,使用form.name.data获取用户提交的数据,可请求结束,数据丢失。用户登录信息应该要保存下来的,否则登陆的意义何在?
为了使请求记住数据,就需要用户会话了。用户会话是一种私有存储,存在于客户端的cookie中。这里我们用请求上下文中名为session的变量实现。
from flask import Flask,render_template,session,url_for,redirect
from flask.ext.wtf import Form
from flask.ext.bootstrap import Bootstrap
from wtforms import StringField,SubmitField
from wtforms.validators import Required class NameForm(Form):
name = StringField('你的名字?',validators=[Required()])
submit = SubmitField('提交') app = Flask(__name__)
app.config['SECRET_KEY'] = 'ni cai'
bootstrap = Bootstrap(app) @app.route('/',methods=['GET','POST'])
def index():
name = None
nameForm = NameForm() if nameForm.validate_on_submit():
session['name'] = nameForm.name.data
nameForm.name.data = ''
return redirect(url_for('index')) return render_template('index.html',form=nameForm,name=session.get('name')) if __name__ == '__main__':
app.run(debug=True)
注意:
1.这个新版中,name被保存在用户会话session['name']中。所以在多次请求中也能维持会话。存储类型是键值对形式
2.redirect()函数用于生成HTTP重定向,在redirect()函数中,参数是重定向的url,推荐用url_for()生成URL,该函数可以保证URP和定义的路由兼容
3.url_for()函数唯一需指定的参数是端点名。默认状况下,路由的端点是相应视图函数的名字。
4.render_templates()中,使用session.get()直接从会话中获取name参数的值。这里是直接使用get(0获取字典中键对应的值以避免异常情况。
flash消息
请求完成后,有时需要让用户知道状态发生了变化。
这种提示功能是Flask的核心特性,flash()
函数可实现这种效果。
app.py
from flask import Flask,render_template,session,url_for,redirect,flash
from flask.ext.wtf import Form
from flask.ext.bootstrap import Bootstrap
from wtforms import StringField,SubmitField
from wtforms.validators import Required class NameForm(Form):
name = StringField('你的名字?',validators=[Required()])
submit = SubmitField('提交') app = Flask(__name__)
app.config['SECRET_KEY'] = 'ni cai'
bootstrap = Bootstrap(app) @app.route('/',methods=['GET','POST'])
def index():
name = None
nameForm = NameForm() if nameForm.validate_on_submit():
newName = nameForm.name.data if newName == session.get('name'):
session['name'] = nameForm.name.data
nameForm.name.data = ''
return redirect(url_for('index'))
else:
flash('名字输入错误!') return render_template('index.html',form=nameForm,name=session.get('name')) if __name__ == '__main__':
app.run(debug=True)
base.html 文件
{% extends "bootstrap/base.html" %} {% block title %}Flasky {% endblock %} {% block navbar %}
<div class="navbar navbar-inverse" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<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="/">Flasky</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="/">Home</a></li>
</ul>
</div>
</div>
</div>
{% endblock %} {% block content %} <div class="container">
{% for message in get_flashed_messages() %}
<div class="alert alert-warning">
<button type="button" class="close" data-dismiss="alert">×</button>
{{ message }}
</div>
{% endfor %} {% block page_content %}{% endblock %}
</div> {% endblock %}
注意:
1.flash()函数用于给client返回一个异常响应。当然,需要再前端基模板中渲染这些信息。前端可用get_flashed_message()函数获取并渲染消息。
2.这个例子中,使用了bootstrap提供的警报CSS样式渲染警告消息。
python flask学习(3)的更多相关文章
- Python Flask学习笔记之模板
Python Flask学习笔记之模板 Jinja2模板引擎 默认情况下,Flask在程序文件夹中的templates子文件夹中寻找模板.Flask提供的render_template函数把Jinja ...
- Python Flask学习笔记之Hello World
Python Flask学习笔记之Hello World 安装virtualenv,配置Flask开发环境 virtualenv 虚拟环境是Python解释器的一个私有副本,在这个环境中可以安装私有包 ...
- Python Flask学习
开了一个新坑..一直以来对web的前端后端了解比较模糊,所以打算学一个后端框架,写个小博客什么的增长一下姿势水平. 初学嘛,选个相对轻量级一点的,就决定学习flask啦.
- python flask学习第2天 URL中两种方式传参
新创建项目 自己写个url映射到自定义的视图函数 在url中传递参数 app.py from flask import Flask app = Flask(__name__) @app.route ...
- python flask学习(2)
本文主要整理下几个Flask扩展: 0.Flask-Bootstrap:集成Twitter开发的一个开源框架Bootstrap.1.Flask-Script:为Flask程序添加一个命令行解析器2.F ...
- python flask学习(1)与Git基础操作
今天从简单的flask开始完成Flask web开发的学习.今天学习了Git和GitHub项目的提交. Git尝试提交过程中出现了"Could not read from remote re ...
- Python Flask学习之安装SQL,python3,Pycharm(网上下载安装即可)
1,下载时更改pypi源.可以额外安装虚拟化环境:pip install -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.co ...
- python flask学习第1天
flask安装: 第一个flask程序: 用pycharm新建一个flask项目,新建项目的截图如下: app.py代码如下: #从flask这个包中导入Flask这个类 #Flask这个类是项目的核 ...
- Python Flask学习笔记(1)
1.搭建虚拟环境 a. 安装 virtualenv : pip3 install virtualenv b. 建立虚拟环境 : 任意目录下建立一个空文件(我的是 Py_WorkSpace) ,在该文件 ...
随机推荐
- Android终端管理器删除文件夹
终端管理器删除文件夹不能用网上提供的: rm -rf 文件夹名 而要用: rm -r 文件夹名. http://blog.csdn.net/enhancing/article/details/8490 ...
- 理解 Android Fragment
/***************************************************************************************** * 理解 Andr ...
- [Codeforces 715C] Digit Tree
[题目链接] https://codeforces.com/contest/715/problem/C [算法] 考虑点分治 一条路径(x , y)合法当且仅当 : d(x) * 10 ^ dep(x ...
- windows下多进程加协程并发模式
好久没更新博客了.正好最近要整理一下最近这段时间做过的项目以及学习python的一些心得.如标题所示,今天就来说说windows下多进程加协程并发模式.其实网上还是蛮多在linux下的多进程加协程并发 ...
- python虚拟环境管理包virtualenvwrapper
1.打开cmd 2.安装virtualenvwrapper pip install virtualenvwrapper-win 3.配置虚拟环境的位置 新建系统变量默认在c盘 4.新建虚拟环境 mkv ...
- HDU2844(多重部分和)
Coins Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- HUD1686(KMP入门题)
Oulipo Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Subm ...
- Subresource Integrity(子资源一致性)和JS DDos 攻击
以下文章转载自 http://www.cnblogs.com/zoucaitou/p/4505483.html 和 http://www.puronglong.com/blog//2015/04/12 ...
- Structure Streaming和spark streaming原生API访问HDFS文件数据对比
此文已由作者岳猛授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. Structure Stream访问方式 code examples import org.apache.sp ...
- HDU2896【AC自动机-模板】
思路: 因为不同病毒特征码不会相同. AC自动机,然后对于每一个输出即可. 注意:以上字符串中字符都是ASCII码可见字符(不包括回车);G++ MLE. //#include <bits/st ...