Python_WEB框架之Flask
Posted 一只待宰的程序猿
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python_WEB框架之Flask相关的知识,希望对你有一定的参考价值。
前言:
Django:1个重武器,包含了web开发中常用的功能、组件的框架;(ORM、Session、Form、Admin、分页、中间件、信号、缓存、ContenType....);
Tornado:2大特性就是异步非阻塞、原生支持WebSocket协议;
Flask:封装功能不及Django完善,性能不及Tornado,但是Flask的第三方开源组件比丰富;http://flask.pocoo.org/extensions/
Bottle:比较简单;
总结:
都不是我写的!!!不论优劣,不同的工具而已;
小型web应用设计的功能点不多使用Flask;
大型web应用设计的功能点比较多使用的组件也会比较多,使用Django(自带功能多不用去找插件);
如果追求性能可以考虑Tornado;
Flask的socket是基于Werkzeug 实现的,模板语言依赖jinja2模板,在使用Flask之前需要安装一下;
pip3 install flask #安装flask
from werkzeug.wrappers import Request, Response # Flask的socket使用werkzeug实现,所以要导入 werkzeug @Request.application def hellow(request): return Response(\'Hello World\') if __name__ == \'__main__\': from werkzeug.serving import run_simple run_simple(\'localhost\',400,hellow)
Flask简单使用
from flask import Flask app=Flask(__name__) #创建1个Flask实例 @app.route(\'/\') #路由系统生成 视图对应url,1. decorator=app.route() 2. decorator(first_flask) def first_flask(): #视图函数 return \'Hello World\' #response if __name__ == \'__main__\': app.run() #启动socket
一、配置文件
app=Flask(__name__,template_folder=\'templates\',static_url_path=\'/static/\',static_path=\'/zhanggen\')
模板路径: template_folder=\'templates\'
静态文件路径:static_url_path=\'/static/\'
静态文件引入别名:static_path=\'/zhanggen\'
设置为调试环境:app.debug=True (代码修改自动更新)
设置json编码格式 如果为False 就不使用ascii编码:app.config[\'JSON_AS_ASCII\']=False
设置响应头信息Content-Type app.config[\'JSONIFY_MIMETYPE\'] ="application/json;charset=utf-8" (注意 ;charset=utf-8)
二、路由系统
1.动态路由(url传参)
@app.route(\'/user/<name>\')
from flask import Flask app=Flask(__name__) @app.route(\'/<name>\') #设置url传参数 http://127.0.0.1:5000/zhanggen def first_flask(name): #视图必须有对应接收参数 print(name) return \'Hello World\' #response if __name__ == \'__main__\': app.run()
@app.route(\'/post/<int:age>\')
#接收整型数字参数 app=Flask(__name__) @app.route(\'/<int:age>/\') #设置url传参数 http://127.0.0.1:5000/18/ def first_flask(age): #视图必须有对应接收参数 print(age) return \'Hello World\' #response if __name__ == \'__main__\': app.run()
@app.route(\'/post/<float:salary>\')
#接收浮点型型数字参数 app=Flask(__name__) @app.route(\'/<float:salary>/\') #设置url传参数http://127.0.0.1:5000/2345555.8889/ def first_flask(salary): #视图必须有对应接收参数 print(salary) return \'Hello World\' #response if __name__ == \'__main__\': app.run()
@app.route(\'/post/<path:path>\')
# 接收URL链接类型参数 app=Flask(__name__) @app.route(\'/<path:url>/\') #设置url传参数:http://127.0.0.1:5000/http://www.baiu.com/ def first_flask(url): #视图必须有对应接收参数 print(url) return \'Hello World\' #response if __name__ == \'__main__\': app.run()
2、指定允许的请求方法
@app.route(\'/login\', methods=[\'GET\', \'POST\'])
# 指定允许的请求方法 app=Flask(__name__) @app.route(\'/<path:url>/\',methods=[\'get\']) #只允许get请求 def first_flask(url): print(url) return \'Hello World\' #response if __name__ == \'__main__\': app.run()
3、通过别名反向生成url
#反向生成url from flask import Flask,url_for app=Flask(__name__) @app.route(\'/<path:url>\',endpoint=\'name1\') def first_flask(url): print(url_for(\'name1\',url=url)) #如果设置了url参数,url_for(别名,加参数) return \'Hello World\' if __name__ == \'__main__\': app.run()
4、通过app.add_url_rule()调用路由
#方式2通过app.add_url_rule()方法的方式调用路由 app=Flask(__name__) def first_flask(): return \'Hello World\' app.add_url_rule(rule=\'/index/\',endpoint=\'name1\',view_func=first_flask,methods=[\'GET\']) #app.add_url_rule(rule=访问的url,endpoint=路由别名,view_func=视图名称,methods=[允许访问的方法]) if __name__ == \'__main__\': app.run()
5、扩展路由功能:正则匹配url
如果需要一些复杂的匹配规则可以自定义正则匹配url
from flask import Flask, views, url_for from werkzeug.routing import BaseConverter app = Flask(import_name=__name__) class RegexConverter(BaseConverter): """ 自定义URL匹配正则表达式 """ def __init__(self, map, regex): super(RegexConverter, self).__init__(map) self.regex = regex def to_python(self, value): """ 路由匹配时,匹配成功后传递给视图函数中参数的值 :param value: :return: """ return int(value) def to_url(self, value): """ 使用url_for反向生成URL时,传递的参数经过该方法处理,返回的值用于生成URL中的参数 :param value: :return: """ val = super(RegexConverter, self).to_url(value) return val # 添加到flask中 app.url_map.converters[\'regex\'] = RegexConverter @app.route(\'/index/<regex("\\d+"):nid>\') def index(nid): print(url_for(\'index\', nid=\'888\')) return \'Index\' if __name__ == \'__main__\': app.run()
四、视图
1、给Flask视图函数加装饰器
注意如果要给视图函数加装饰器增加新功能,一点要加在路由装饰器下面,才会被路由装饰器装饰,才能生生成url关系;
#给Flask视图加装饰器 #1、定义1个装饰器 def auth(func): print(\'我在上面\') def inner(*args,**kwargs): return func(*args,**kwargs) return inner app=Flask(__name__) @app.route(\'/\',methods=[\'GET\']) @auth #注意如果要给视图函数加装饰器,一点要加在路由装饰器下面,才会被路由装饰器装饰 def first_flask(): print(\'ffff\') return \'Hello World\' if __name__ == \'__main__\': app.run()
2、request和response
a.请求相关信息
request.method: 获取请求方法
request.json
request.json.get("json_key"):获取json数据 **较常用
request.argsget(\'name\') :获取get请求参数
request.form.get(\'name\') :获取POST请求参数
request.form.getlist(\'name_list\'):获取POST请求参数列表(多个)
request.values.get(\'age\') :获取GET和POST请求携带的所有参数(GET/POST通用)
request.cookies.get(\'name\'):获取cookies信息
request.headers.get(\'Host\'):获取请求头相关信息
request.path:获取用户访问的url地址,例如(/,/login/,/ index/);
request.full_path:获取用户访问的完整url地址+参数 例如(/login/?age=18)
request.script_root: 抱歉,暂未理解其含义;
request.url:获取访问url地址,例如http://127.0.0.1:5000/?age=18;
request.base_url:获取访问url地址,例如 http://127.0.0.1:5000/;
request.url_root
request.host_url
request.host:获取主机地址
request.files:获取用户上传的文件
obj = request.files[\'the_file_name\']
obj.save(\'/var/www/uploads/\' + secure_filename(f.filename)) 直接保存
b、响应相关信息
return "字符串" :响应字符串
return render_template(\'html模板路径\',**{}):响应模板
return redirect(\'/index.html\'):跳转页面
响应json数据
方式1: return jsonify(user_list)
app.config[\'JSON_AS_ASCII\']=False #指定json编码格式 如果为False 就不使用ascii编码, app.config[\'JSONIFY_MIMETYPE\'] ="application/json;charset=utf-8" #指定浏览器渲染的文件类型,和解码格式;
方式2:
return Response(data,mimetype="application/json;charset=utf-8",)
如果需要设置响应头就需要借助make_response()方法
from flask import Flask,request,make_response
response = make_response(render_template(\'index.html\'))
response是flask.wrappers.Response类型
response.delete_cookie(\'key\')
response.set_cookie(\'key\', \'value\')
response.headers[\'X-Something\'] = \'A value\'
return respons
3 、Flask之CBV视图
#CBV视图 from flask import Flask,url_for,views #----------------------------------------------------- app=Flask(__name__) #装饰器 def auth(func): print(\'我在上面\') def inner(*args,**kwargs): return func(*args,**kwargs) return inner #-------------------------------------------------------- class IndexView(views.MethodView): #CBV视图 methods=[\'GET\'] #允许的http请求方法(改CBV只允许GET方法) decorators = [auth,] #每次请求过来都加auth装饰器 def get(self): return \'Index.GET\' def post(self): return \'Index.POST\' app.add_url_rule(\'/index/\',view_func=IndexView.as_view(name=\'name1\')) #(name=\'name1\'反向生成url别名 if __name__ == \'__main__\': app.run()
五、模板语言
Flask使用的是Jinja2模板,所以其语法和Django无差别(Django的模板语言参考Jinja2)
1.引用静态文件
方式1:别名引入
<link rel="stylesheet" href="/zhanggen/commons.css">
方式2:url_for()方法引入
<link rel="stylesheet" href="{{ url_for(\'static\',filename=\'commons.css\') }}">
2.模板语言引用上下文对象
变量
<h1>{{user_list}}</h1> <!--变量 -->
Flask的Jinjia2可以通过Context 把视图中的函数传递把模板语言中执行,这就是Django中的simple_tag和simple_fifter;
simple_tag(只能传2个参数,支持for、if)
@app.template_global() #simple_tag def foo(arg): return \'<input type="text">\'
<h1>{{foo(1)|safe}}</h1> <!--Flask的模板语言支持simple_tag-->
simple_fifter(对参数个数无限制,不支持for、if)
@app.template_filter() #simple_fifter def foo1(arg1,arg2,arg3): return arg1+arg2+arg3
<h1> {{ \'alex\'|foo1(\'s \',\'b\',) }} </h1> <!-- simple_fifter -->
3.wtform(flask表单验证插件)
3.0.简介
wtforms WTForms是一个支持多个web框架的form组件,主要对用户请求数据 进行表单验证。
3.1. 安装
pip install wtforms #安装wtfroms插件
3.2.简单使用
wtforms和Django自带的form验证插件功能相同,使用起来大同小异;
用户登录页面验证
#!/usr/bin/env python # -*- coding:utf-8 -*- from flask import Flask, render_template, request, redirect from wtforms import Form from wtforms.fields import core from wtforms.fields import html5 from wtforms.fields import simple from wtforms import validators from wtforms import widgets app=Flask(__name__,template_folder=\'templates\') #知道模板文件 app.debug=True #登录验证实例 class LoginForm(Form): #不同的字段 内部包含正则表达式 html5.EmailField | html5.DateTimeField... name=simple.StringField( label=\'用户名\', validators=[ #验证规则和错误提示信息 validators.DataRequired(message=\'用户名不能为空.\'), validators.Length(min=6, max=18, message=\'用户名长度必须大于%(min)d且小于%(max)d\') ], widget=widgets.TextInput(), #前端页面显示的插件.TextArea render_kw={\'class\': \'form-control\'} #设置form标签的class信息 ) # 不同的字段 内部包含正则表达式 html5.EmailField | html5.DateTimeField... pwd = simple.PasswordField( label=\'密码\', validators=[ validators.DataRequired(message=\'密码不能为空.\'), validators.Length(min=8, message=\'用户名长度必须大于%(min)d\'), #自定义验证规则 validators.Regexp(regex="^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[$@$!%*?&])[A-Za-z\\d$@$!%*?&]{8,}", message=\'密码至少8个字符,至少1个大写字母,1个小写字母,1个数字和1个特殊字符\') ], widget=widgets.PasswordInput(), render_kw={\'class\': \'form-control\'} ) @app.route(\'/login/\', methods=[\'GET\', \'POST\']) def login(): if request.method == \'GET\': form = LoginForm() #实例化 form验证类 return render_template(\'login.html\', form=form) else: form = LoginForm(formdata=request.form) if form.validate(): #判断是否验证成功? print(\'用户提交数据通过格式验证,提交的值为:\', form.data) else: print(form.errors) return render_template(\'login.html\', form=form) if __name__ == \'__main__\': app.run()
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>登录</h1> <form method="post" novalidate> <!--<input type="text" name="name">--> <p>{{form.name.label}} {{form.name}} {{form.name.errors[0] }}</p> <!--<input type="password" name="pwd">--> <p>{{form.pwd.label}} {{form.pwd}} {{form.pwd.errors[0] }}</p> <input type="submit" value="提交"> </form> </body> </html> login.html
用户注册页面验证
#用户注册 from flask import Flask, render_template, request, redirect from wtforms import Form from wtforms.fields import core from wtforms.fields import html5 from wtforms.fields import simple from wtforms import validators from wtforms import widgets app = Flask(__name__, template_folder=\'templates\') app.debug = True class RegisterForm(Form): name = simple.StringField( label=\'用户名\', validators=[ validators.DataRequired() ], widget=widgets.TextInput(), render_kw={\'class\': \'form-control\'}, default=\'张根\' #设置input标签中默认值 ) pwd = simple.PasswordField( label=\'密码\', validators=[ validators.DataRequired(message=\'密码不能为空.\') ], widget=widgets.PasswordInput(), render_kw={\'class\': \'form-control\'} ) pwd_confirm = simple.PasswordField( #第二次输入密码 label=\'重复密码\', validators=[ validators.DataRequired(message=\'重复密码不能为空.\'), validators.EqualTo(\'pwd\', message="两次密码输入不一致") #验证2次输入的密码是否一致? ], widget=widgets.PasswordInput(), render_kw={\'class\': \'form-control\'} ) email = html5.EmailField( label=\'邮箱\', validators=[ validators.DataRequired(message=\'邮箱不能为空.\'), validators.Email(message=\'邮箱格式错误\') ], widget=widgets.TextInput(input_type=\'emailFlask之模板之宏继承包含