Flask篇:flask路由系统、flask模板语法、flask请求响应

一、路由系统

1.路由使用

flask 路由写法:

基于装饰器

复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
from flask import Flask app = Flask(__name__) @app.route('/index', methods=['GET'], endpoint='index') # 第一个参数为url路径,第二个参数为请求方式,第三个为路由名称 def index(): return 'hello'

另一种写法(与django类似)

复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
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类型)

例如:

复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
@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

复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
@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
复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
@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方法即可完成路由的配置

复制代码
  • 1
  • 2
  • 3
  • 4
# 示例 app.add_url_rule('/order/<string:pk>',view_func=order) app.add_url_rule('/index',view_func=index)

4.基于类的视图cbv

4.1 cbv写法

复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
# 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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
(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添加装饰器和请求方式

复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
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 参数

复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
-rule:请求的路径,可以使用转换器 -endpoint:别名--》反向解析 -view_func:视图类.as_view(name='xx')(视图函数内存地址) -methods:允许的请求方式 # ---------以下不重要----- -defaults:字典,给视图函数传默认值 -strict_slashes:对URL最后的 / 符号是否严格要求 -redirect_to

5.2 @app.route源码分析 ---> add_url_rule

复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
# 装饰器 @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 模板语法

复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
# 模板语法: -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、添加响应头)

复制代码
  • 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
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
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()
posted @   马氵寿  阅读(215)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
展开