做相册集什么网站,模仿做网站,网络营销分析,做秩序册的网站Flask快速入门#xff08;路由、CBV、请求和响应、session#xff09; 目录 Flask快速入门#xff08;路由、CBV、请求和响应、session#xff09;安装创建页面Debug模式快速使用Werkzeug介绍watchdog介绍快速体验 路由系统源码分析手动配置路由动态路由-转换器 Flask的CBV…Flask快速入门路由、CBV、请求和响应、session 目录 Flask快速入门路由、CBV、请求和响应、session安装创建页面Debug模式快速使用Werkzeug介绍watchdog介绍快速体验 路由系统源码分析手动配置路由动态路由-转换器 Flask的CBV快速使用cbv源码分析 请求和响应请求对象(request)响应对象 Session基本使用原理解析 安装
pip install flask创建页面
from flask import Flask# 用当前脚本名称实例化Flask对象方便flask从该脚本文件中获取需要的内容
app Flask(__name__)# 配置路由和视图函数的对应关系(基于装饰器)
app.route(/)
def index():return Hello World!# 启动一个本地开发服务器激活该网页
app.run()
# 或者
# if __name__ __main__:
# app.run()Debug模式
终端执行
if __name__ __main__:app.debug Trueapp.run()debug模式下
自动重载 - 根据代码内容变化自动重启项目终端展示错误提示日志记录
快速使用
用route接受请求方式
app.route(/, methods[GET, POST])
def index():return 你好直接调用请求方法
app.get(/)
def index():return 你好Werkzeug介绍
Werkzeug是一个WSGI工具包他可以作为一个Web框架的底层库它并没有和flask有直接联系但是flask可以借助它执行各种Web操作例如RequestResponse
from werkzeug.wrappers import Request, Responseapp.route(/)
def index():return Response(你好)watchdog介绍
快速体验
当前目录下修改文件会被监控并打印日志
import sys
import time
import logging
from watchdog.observers import Observer
from watchdog.events import LoggingEventHandlerif __name__ __main__:# 配置日志logging.basicConfig(levellogging.INFO,format%(asctime)s - %(message)s,datefmt%Y-%m-%d %H:%M:%S)path sys.argv[1] if len(sys.argv) 1 else .# 初始化监控类(文件的创建 删除...)event_handler LoggingEventHandler()# 初始化监控类observer Observer()# 配置 observer 以使用 event_handler 来处理 path 路径下的事件并递归地监控该路径下的所有子目录由于 recursiveTrueobserver.schedule(event_handler, path, recursiveTrue)# 启动监控observer.start()try:while True:time.sleep(1)except KeyboardInterrupt:observer.stop()observer.join()路由系统
源码分析
app.route(/,methods[GET])直接Ctrl左键进入route
setupmethod
def route(self, rule: str, **options: t.Any) - t.Callable[[T_route], T_route]:# 将视图函数作为参数执行了add_url_ruledef decorator(f: T_route) - T_route:endpoint options.pop(endpoint, None)self.add_url_rule(rule, endpoint, f, **options)return freturn decorator该注释的意思是当有给定的url规则来注册该视图函数时将会触发该装饰器且装饰器会执行add_url_rule方法因此我们只需要搞明白add_url_rule做了什么
setupmethod
def add_url_rule(self,rule: str,endpoint: str | None None,view_func: ft.RouteCallable | None None,provide_automatic_options: bool | None None,**options: t.Any,
) - None:rule定义路由的字符串例如/、/loginendpoint当URL中无参数函数需要参数时使用defaults {‘k’: ‘v’}-为函数提供参数django中也有叫kwargs默认为Noneview_func视图函数的名称也就是源码中的fprovide_automatic_options: 一个布尔值用于控制是否应该自动为路由添加一个 OPTIONS 方法的处理器。如果为 None则使用应用配置的 ADD_AUTOMATIC_OPTIONS 值options: 一个可变参数用于传递额外的选项给路由。这些选项可以包括用于路由的各种配置如 HTTP 方法的集合methods
手动配置路由
知晓了路由原理后我们就可以不用装饰器自定义路由
def login():return 我是loginapp.add_url_rule(/login, endpointNone, view_funclogin, methods[GET, POST])动态路由-转换器
大致与Django同理
# 转换器
app.add_url_rule(/index/int:pk)pk值是一个int类型的任意参数除此之外还有其他类型参数
DEFAULT_CONVERTERS {default: UnicodeConverter,string: UnicodeConverter,any: AnyConverter,path: PathConverter,int: IntegerConverter,float: FloatConverter,uuid: UUIDConverter,
}Flask的CBV
CBVClass-Based Views指的是基于类的视图编写方式
快速使用
from flask import Flask, url_for
from flask.views import MethodViewapp Flask(__name__)
app.debug Trueclass IndexView(MethodView):def get(self):return get请求def post(self):return post请求# name可以理解为别名
app.add_url_rule(/index, view_funcIndexView.as_view(nameindex))if __name__ __main__:app.run()# CBV也可以使用路由装饰器
# route(/index)
# class IndexView(MethodView): 即传了endpoint又传了name以谁为准
如果传了endpoint以endpoint 为准 如果没传以函数名为准函数名是view但是被name改了所以以name为准
cbv源码分析
class View:methods: t.ClassVar[t.Collection[str] | None] Noneprovide_automatic_options: t.ClassVar[bool | None] Nonedecorators: t.ClassVar[list[t.Callable[[F], F]]] []init_every_request: t.ClassVar[bool] Truedef dispatch_request(self) - ft.ResponseReturnValue:raise NotImplementedError()classmethoddef as_view(cls, name: str, *class_args: t.Any, **class_kwargs: t.Any) - ft.RouteCallable:if cls.init_every_request:def view(**kwargs: t.Any) - ft.ResponseReturnValue:self view.view_class( # type: ignore[attr-defined]*class_args, **class_kwargs)# 这里其实就是return self.dispatch_request(**kwargs)return current_app.ensure_sync(self.dispatch_request)(**kwargs) # type: ignore[no-any-return]else:self cls(*class_args, **class_kwargs)def view(**kwargs: t.Any) - ft.ResponseReturnValue:return current_app.ensure_sync(self.dispatch_request)(**kwargs) # type: ignore[no-any-return]if cls.decorators:# 将view的名字改为传入的name 否则一直叫viewview.__name__ nameview.__module__ cls.__module__for decorator in cls.decorators:view decorator(view)view.view_class cls # type: ignoreview.__name__ nameview.__doc__ cls.__doc__view.__module__ cls.__module__view.methods cls.methods # type: ignoreview.provide_automatic_options cls.provide_automatic_options # type: ignorereturn view每当有请求过来时执行view()执行view的本质就是执行dispatch_request()self就是我们定义的视图类对象
请求和响应
请求对象(request)
from flask import Flask, request响应对象
make_response生成的响应对象可以存放字符串、模板、重定向、json
from flask import Flask, render_template, make_responseclass ContactView(MethodView):def get(self):res make_response(get请求)res.set_cookie(name, NAME, path/contact)return res可以对响应对象添加cookiepath的意思是只有path指定的路径会存储cookie浏览其他页面不会携带cookie
Session
基本使用
# 配置secret_key 自定义的字符串
app.secret_key abcdefg增session[name] 张三删session.pop(name)清session.clear()取name session.get(name)
原理解析
存储或修改session时 对session进行加密(三段式)存储到cookie(obj.set_cookie) 校验session时 根据session取出cookie将第二段反解放入session中
源码
# open_session
def open_session(self, app: Flask, request: Request) - SecureCookieSession | None:s self.get_signing_serializer(app)if s is None:return Noneval request.cookies.get(self.get_cookie_name(app))if not val:return self.session_class()max_age int(app.permanent_session_lifetime.total_seconds())try:data s.loads(val, max_agemax_age)return self.session_class(data)except BadSignature:return self.session_class()# save_session
def save_session(self, app: Flask, session: SessionMixin, response: Response) - None:name self.get_cookie_name(app)domain self.get_cookie_domain(app)path self.get_cookie_path(app)secure self.get_cookie_secure(app)samesite self.get_cookie_samesite(app)httponly self.get_cookie_httponly(app)# Add a Vary: Cookie header if the session was accessed at all.if session.accessed:response.vary.add(Cookie)# If the session is modified to be empty, remove the cookie.# If the session is empty, return without setting the cookie.if not session:if session.modified:response.delete_cookie(name,domaindomain,pathpath,securesecure,samesitesamesite,httponlyhttponly,)response.vary.add(Cookie)returnif not self.should_set_cookie(app, session):returnexpires self.get_expiration_time(app, session)val self.get_signing_serializer(app).dumps(dict(session)) # type: ignoreresponse.set_cookie(name,val, # type: ignoreexpiresexpires,httponlyhttponly,domaindomain,pathpath,securesecure,samesitesamesite,)response.vary.add(Cookie)