Flask篇:flask路由系统、flask模板语法、flask请求响应
目录
一、路由系统
1.路由使用
flask 路由写法:
基于装饰器
from flask import Flask
app = Flask(__name__)
@app.route('/index', methods=['GET'], endpoint='index') # 第一个参数为url路径,第二个参数为请求方式,第三个为路由名称
def index():
return 'hello'
另一种写法(与django类似)
from flask import Flask
app = Flask(__name__)
@app.route('/index', methods=['GET'], endpoint='index') # 第一个参数为url路径,第二个参数为请求方式,第三个为路由名称
def index():
return 'hello'
app.add_url_rule('/index', view_func=index,)
2.转换器
转换器不设置类型时默认为default
转换器类型 | 获取到的值类型 |
---|---|
default | UnicodeConverter(传入什么类型数据就是什么类型) |
string | UnicodeConverter(传入什么类型数据就是什么类型) |
any | AnyConverter(任意类型) |
path | PathConverter (可以识别/的url类型) |
int | IntegerConverter(整数类型) |
float | FloatConverter(浮点数类型) |
uuid | UUIDConverter(uuid类型) |
例如:
@app.route('/index/<pk>', methods=['GET'], endpoint='index') #默认类型转化器
def index(pk):
return 'hello'
@app.route('/index/<int:pk>', methods=['GET'], endpoint='index') #指定类型转换器
def index(pk):
return 'hello'
3.路由本质
从@app.route寻找源码,route会运行add_url_rule
@setupmethod
def route(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]:
def decorator(f: T_route) -> T_route:
endpoint = options.pop("endpoint", None)
self.add_url_rule(rule, endpoint, f, **options) # 此处是重点
return f
return decorator
@setupmethod
def add_url_rule(
self, # 此处的self是app
rule: str,
endpoint: t.Optional[str] = None,
view_func: t.Optional[ft.RouteCallable] = None,
provide_automatic_options: t.Optional[bool] = None,
**options: t.Any,
) -> None:
def decorator(f: F) -> F:
self.view_functions[endpoint] = f
return f
return decorator
而app对象自身是没有add_url_rule方法的
运行时寻找add_url_rule方法是Flask类的
结合以上的代码分析
我们只需要自己实现add_url_rule方法即可完成路由的配置
# 示例
app.add_url_rule('/order/<string:pk>',view_func=order)
app.add_url_rule('/index',view_func=index)
4.基于类的视图cbv
4.1 cbv写法
# cbv写法,继承MethodView,跟djagno很像
from flask.views import MethodView
class Home(MethodView):
methods=['POST']
# decorators = (装饰器名字,装饰器名字2,)
def get(self):
return 'home'
def post(self):
return 'home-post'
app.add_url_rule('/home', view_func=Home.as_view(name='home'))
4.2 cbv源码分析
(1) as_view的name是别名,fbv的endpoint是别名,现在写cbv,name它最终也是endpoint,而且必须写,即便写了endpoint
(2) Home.as_view是view函数的内存地址,请求来了执行MethodView中的:
self.dispatch_request(), # 重写了dispatch_request-->根据请求方式执行视图类中跟请求方式同名的方法,因此如果视图类继承了View,需要重写dispatch_request
(3) dispatch_request源码: # 最新版本跟老版本有所不同,逻辑基本上一样,通过请求方式不同进行反射,然后执行类的对应方法
def dispatch_request(self, **kwargs: t.Any) -> ft.ResponseReturnValue:
meth = getattr(self, request.method.lower(), None)
# If the request method is HEAD and we don't have a handler for it
# retry with GET.
if meth is None and request.method == "HEAD":
meth = getattr(self, "get", None)
assert meth is not None, f"Unimplemented method {request.method!r}"
return current_app.ensure_sync(meth)(**kwargs)
(4) fbv和cbv别名
app.add_url_rule('/index', view_func=index) # 路由有个别名,如果不写endpoint,会以函数名作为endpoint
app.add_url_rule('/home', view_func=Home.as_view(name='home')) # name就是路径的别名,endpoint
4.3 cbv添加装饰器和请求方式
class Home(MethodView):
methods=['POST']
decorators = (装饰器名字,装饰器名字2,) # 最左边的在最下面
def get(self):
return 'home'
def post(self):
return 'home-post'
(1) cbv加装饰器, 在类中写 decorators = (装饰器名字,装饰器名字2,),第一个位置的会放在最下层,多个装饰器执行顺序是从【上往下执行】
(2) cbv只允许某个请求方式 methods=['POST']
5.add_url_rule参数
5.1 参数
-rule:请求的路径,可以使用转换器
-endpoint:别名--》反向解析
-view_func:视图类.as_view(name='xx')(视图函数内存地址)
-methods:允许的请求方式
# ---------以下不重要-----
-defaults:字典,给视图函数传默认值
-strict_slashes:对URL最后的 / 符号是否严格要求
-redirect_to
5.2 @app.route源码分析 ---> add_url_rule
# 装饰器 @route python特殊语法糖,会把下面的函数当参数传入 order=route(order) 以后调用order本质就是在执行route(order)()
# route的内层函数---->本质是self.add_url_rule(rule, endpoint, f, **options)
@setupmethod
def route(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]:
def decorator(f: T_route) -> T_route:
endpoint = options.pop("endpoint", None)
self.add_url_rule(rule, endpoint, f, **options) # self是app对象,add_url_rule 其实就是Flask类的add_url_rule方法
return f
return decorator
# 所以我们可以不使用装饰器来注册路由,而自己写add_url_rule来注册路由,这就跟django比较相似了
app.add_url_rule('/order/<string:pk>',view_func=order)
app.add_url_rule('/index',view_func=index)
二、模板
2.1 模板语法
# 模板语法:
-django 是自己的模板语法,dtl
-flask使用第三方,兼容dtl,但是它可以加括号,可以使用[],处理了xss攻击
-xss,csrf,cors分别是什么?
-django,flask处理了xss攻击,不存在这个攻击,原理是什么?
-使用了html的特殊字符替换,但是如果使用了 |safe 或者Markup ,就不会渲染到页面上
from flask import Flask,render_template,Markup
app=Flask(__name__)
@app.route('/')
def index():
#----------------------------------------------------------
a='<a href="http://www.baidu.com">点我看美女</a>'
a=Markup(a)
#----------------------------------------------------------
return render_template('home.html',name='lz',age=19,url=a,add=add)
if __name__ == '__main__':
app.run()
三、Flask请求响应(请求对象属性方法;响应四件套、响应设置cookie、添加响应头)
from flask import Flask, request,make_response,render_template
app = Flask(__name__)
app.debug=True
@app.route('/login.html', methods=['GET', "POST"])
def login():
####请求对象的属性和方法####
# request:是全局的request,用起来就当是每个请求都有一个request即可
print(request.method) # 请求方式
print(request.args) # get 请求提及的数据
print(request.form) # post提交的数据
print(request.values) # get,post提交的数据总和
print(request.cookies) # cookies
print(request.headers) # 请求头
print(request.path) # 不带域名,请求路径
print(request.full_path) # 全路径,不带域名,带参数的请求路径
print('-----',request.script_root)
print(request.url) # 带域名带参数的请求路径
print(request.base_url) # 带域名请求路径
print(request.url_root) # 域名
print(request.host_url) # 域名+端口
print(request.host) # 不带http的域名+端口
from werkzeug.datastructures import FileStorage
print(type(request.files.get('files')))
# obj = request.files['files']
# obj.save('/var/www/uploads/' + secure_filename(f.filename))
### 响应对象四件套,设置cookie和响应头
## 1 响应四件套
# return "字符串"
# return render_template('html模板路径',**{})
# return redirect('/index.html')
# return jsonify({'k1':'v1'})
## 2 向浏览器中写入cookie,四件套都可以使用make_response包裹一下变成响应对象
res=make_response(render_template('home.html'))
res.set_cookie('name','lqz')
# delete_cookie 删除cookie
## 3 向浏览器中写响应头
# res.headers['X-Something'] = 'A value'
return res
if __name__ == '__main__':
app.run()