文章目录
- [Flask Web开发:基于Python的Web应用开发实战.第2版.pdf 先看到第5章](#Flask Web开发:基于Python的Web应用开发实战.第2版.pdf 先看到第5章)
- 应用的基本结构
-
- [2.1 初始化 所有Flask应用都必须创建一个应用实例](#2.1 初始化 所有Flask应用都必须创建一个应用实例)
-
- [Flask(name) 是 Flask 的"定位系统",用它来确定项目根路径](#Flask(name) 是 Flask 的“定位系统”,用它来确定项目根路径)
-
- [name 只和"当前这个 .py 文件是怎么被 import 的"有关](#name 只和“当前这个 .py 文件是怎么被 import 的”有关)
- [2.2 路由 处理URL和函数之间关系的程序称为路由。](#2.2 路由 处理URL和函数之间关系的程序称为路由。)
- [2.7 命令行选项](#2.7 命令行选项)
-
- --host
-
- 在哪个网络接口上监听客户端发来的连接
- [什么是 0.0.0.0?](#什么是 0.0.0.0?)
-
- [127.0.0.1 / localhost / 0.0.0.0 的本质区别](#127.0.0.1 / localhost / 0.0.0.0 的本质区别)
- [你的电脑其实有多个 IP(ipconfig)](#你的电脑其实有多个 IP(ipconfig))
- [2.8.1 应用和请求上下文](#2.8.1 应用和请求上下文)
-
- [为了同时服务多个客户端,Web 服务器必须并发处理请求,而并发最常见的方式就是多线程(或多进程 / 协程)。](#为了同时服务多个客户端,Web 服务器必须并发处理请求,而并发最常见的方式就是多线程(或多进程 / 协程)。)
-
- [Flask 开发服务器也是"多线程"的(默认)](#Flask 开发服务器也是“多线程”的(默认))
- 为什么你"感觉不到"多线程?
- [flask上下文,Flask 通过应用上下文和请求上下文,把"本应作为参数传递的对象"绑定到当前线程,使开发者可以像使用全局变量一样访问它们,同时又保证在并发环境下互不干扰](#flask上下文,Flask 通过应用上下文和请求上下文,把“本应作为参数传递的对象”绑定到当前线程,使开发者可以像使用全局变量一样访问它们,同时又保证在并发环境下互不干扰)
-
- [flask在处理某个请求时,我给当前线程贴一张标签:这次你处理的是哪一个请求、哪一个应用。" 这张"标签",就是 上下文](#flask在处理某个请求时,我给当前线程贴一张标签:这次你处理的是哪一个请求、哪一个应用。” 这张“标签”,就是 上下文)
- [应用上下文(Application Context)](#应用上下文(Application Context))
- [请求上下文(Request Context)](#请求上下文(Request Context))
- [为什么要分成"应用上下文 + 请求上下文"?](#为什么要分成“应用上下文 + 请求上下文”?)
- [Flask 是什么时候"推送 / 弹出"上下文的?](#Flask 是什么时候“推送 / 弹出”上下文的?)
- 为什么"推送后就能直接用变量"?
- 总结
- [2.8.2 请求分发](#2.8.2 请求分发)
-
- app.url_map
-
- [HTTP 方法](#HTTP 方法)
- [为什么你只写了 GET,却看到三个方法?](#为什么你只写了 GET,却看到三个方法?)
- [2.8.3 请求对象](#2.8.3 请求对象)
-
- 表单数据:form
- [URL 查询参数:args](#URL 查询参数:args)
- values
- cookies
- headers
- files
-
- [Flask 接收到的文件本质上是什么?二进制流](#Flask 接收到的文件本质上是什么?二进制流)
- get_data()
- get_json()
- blueprint
- endpoint
- method
- scheme
- is_secure()
- host
- path
- query_string
- full_path
- url
- base_url
- remote_addr
- environ
- 请求钩子
-
- [g 是钩子与视图之间共享数据的桥梁](#g 是钩子与视图之间共享数据的桥梁)
- [2.8.5 响应](#2.8.5 响应)
-
- status_code
- headers
-
- 常用头部content-type/length
- [Cookie 与缓存头的区别,Cache-Control / Expires](#Cookie 与缓存头的区别,Cache-Control / Expires)
-
- cookie
- [Cache-Control / Expires 记录这个页面可以缓存多久](#Cache-Control / Expires 记录这个页面可以缓存多久)
- 不是所有头部都需要手动添加
- Authorization,token
-
- token是什么?客户端证明自己身份的"通行证"。证明自己可以访问服务端。服务端根据它来判断你能不能访问接口
- [token 在哪里携带?](#token 在哪里携带?)
-
- headers(最常用,最安全)
- [Authorization(授权),HTTP 请求头(Header)的一种,它的作用是 告诉服务器"我是谁"或者"我有权限"。服务器根据它来判断你能不能访问接口。](#Authorization(授权),HTTP 请求头(Header)的一种,它的作用是 告诉服务器“我是谁”或者“我有权限”。服务器根据它来判断你能不能访问接口。)
- [Authorization 的基本格式,Authorization: <scheme> <credentials>,<scheme> → 认证方式/类型,<credentials> → 认证凭证/证明内容。<scheme>告诉服务器 后面的凭证怎么解析、怎么验证.<credentials>身份证明的内容](#Authorization 的基本格式,Authorization: <scheme> <credentials>,<scheme> → 认证方式/类型,<credentials> → 认证凭证/证明内容。<scheme>告诉服务器 后面的凭证怎么解析、怎么验证.<credentials>身份证明的内容)
- url参数(不安全)
- [cookie, 用户登录网站,服务器会把 token 放到 Cookie 里,浏览器收到后,每次访问同一网站(服务器),会 自动把这个 token 带上](#cookie, 用户登录网站,服务器会把 token 放到 Cookie 里,浏览器收到后,每次访问同一网站(服务器),会 自动把这个 token 带上)
- [什么时候 Cookie 不够?](#什么时候 Cookie 不够?)
- [cookie 和 token区别。token验证身份,cookie保存登录状态,偏好等](#cookie 和 token区别。token验证身份,cookie保存登录状态,偏好等)
- [set_cookie(key, value, **options)。cookie 是服务器生成的,发送给浏览器的。浏览器负责保存和回传](#set_cookie(key, value, **options)。cookie 是服务器生成的,发送给浏览器的。浏览器负责保存和回传)
-
- [下次访问同一网站(服务器) → 浏览器自动在请求里带上 cookie,满足域名,路径,未过期,自动在向这个服务器发送的所有请求中带上](#下次访问同一网站(服务器) → 浏览器自动在请求里带上 cookie,满足域名,路径,未过期,自动在向这个服务器发送的所有请求中带上)
- [set_cookie() 时,可以指定 cookie 生效的范围,主要是通过 domain(域名)和 path(路径) 来控制的](#set_cookie() 时,可以指定 cookie 生效的范围,主要是通过 domain(域名)和 path(路径) 来控制的)
-
- [max_age 和 expires 都是过期时间,它们有什么区别](#max_age 和 expires 都是过期时间,它们有什么区别)
- 总结
- [delete_cookie(key, **options)](#delete_cookie(key, **options))
- content_length
- content_type
- set_data(data)
- get_data(as_text=False)
- 重定向
-
- redirect
- [错误处理 abort()](#错误处理 abort())
Flask Web开发:基于Python的Web应用开发实战.第2版.pdf 先看到第5章
Flask Web开发:基于Python的Web应用开发实战.第2版.pdf

应用的基本结构
2.1 初始化 所有Flask应用都必须创建一个应用实例
Flask(name) 是 Flask 的"定位系统",用它来确定项目根路径
app = Flask(__name__)
name 是告诉 Flask:
"这个 Flask 应用的根目录在哪里"
Flask 用它来 找模板、静态文件、资源路径


name 只和"当前这个 .py 文件是怎么被 import 的"有关
当一个 Python 文件被 import 时,name 就等于"import 用的那个名字",用import理解就行,不用fromxximportxx

2.2 路由 处理URL和函数之间关系的程序称为路由。
URL 映射 = 客户端访问的地址(如:浏览器访问的地址) → Python 中哪个函数来处理

端点

2.7 命令行选项
--host
--host 0.0.0.0 表示 Flask 监听本机所有网络接口,使同一网络中的其他计算机可以通过该机器的局域网 IP 访问服务,而不是通过 0.0.0.0 本身访问。
在哪个网络接口上监听客户端发来的连接


什么是 0.0.0.0?




127.0.0.1 / localhost / 0.0.0.0 的本质区别
127.0.0.1 和 localhost 只能在"本机"访问;
使用 0.0.0.0 监听后,别的电脑是通过"你这台机器的真实 IP"访问的,而不是通过 0.0.0.0







你的电脑其实有多个 IP(ipconfig)


2.8.1 应用和请求上下文
写起来像全局,用起来像参数,底层是线程安全的
为了同时服务多个客户端,Web 服务器必须并发处理请求,而并发最常见的方式就是多线程(或多进程 / 协程)。


同一份视图函数会被多个线程并发执行


Flask 开发服务器也是"多线程"的(默认)

为什么你"感觉不到"多线程?

flask上下文,Flask 通过应用上下文和请求上下文,把"本应作为参数传递的对象"绑定到当前线程,使开发者可以像使用全局变量一样访问它们,同时又保证在并发环境下互不干扰

为什么需要上下文

flask在处理某个请求时,我给当前线程贴一张标签:这次你处理的是哪一个请求、哪一个应用。" 这张"标签",就是 上下文



Flask 在处理每一个请求时,会临时创建两个上下文:
应用上下文提供当前应用和请求级临时存储(current_app、g);
请求上下文提供当前请求和会话信息(request、session);
请求结束后,这些上下文都会被销毁,从而保证线程安全。
应用上下文(Application Context)





请求上下文(Request Context)


为什么要分成"应用上下文 + 请求上下文"?

Flask 是什么时候"推送 / 弹出"上下文的?

为什么"推送后就能直接用变量"?

总结

2.8.2 请求分发
app.url_map




HTTP 方法


为什么你只写了 GET,却看到三个方法?

2.8.3 请求对象

表单数据:form

URL 查询参数:args

values

cookies

headers

files
"客户端上传的文件列表",每个文件都是一个对象,可以直接读取内容或者保存到服务器"。






Flask 接收到的文件本质上是什么?二进制流



保存文件和文件类型无关。不过保存错类型,查看会不方便。所以保存文件时最好用正确后缀


为什么打开能看懂,不是二进制?文件的类型(文本、图片、音频、视频)只是约定告诉操作系统或软件怎么解析二进制。所有文件在磁盘上都是二进制的。


从计算机底层来说,任何数据最终都是二进制,无论是在磁盘、内存还是网络上传输。字节是计算机用来打包、存储和传输二进制的最小单位。网络传输、文件读写、内存操作,都是以字节为单位处理



get_data()

get_json()
get_json() 就是把请求体里的 JSON 数据 解析成 Python 对象(通常是字典或列表)。


blueprint

endpoint

method

scheme

is_secure()

host

path

query_string

full_path

url

base_url

remote_addr

environ

请求钩子
在每个请求处理流程中,允许我们注册一些函数,在请求开始之前、请求结束之后或特定条件下自动执行,从而避免在每个视图函数里重复代码

# 使用方法: 装饰器
from flask import Flask, g, request
app = Flask(__name__)
# 每次请求前执行
@app.before_request
def before_request_func():
# 假设从请求头获取用户信息
g.user = request.headers.get("X-User")
print("请求开始,用户:", g.user)
# 只在第一个请求前执行一次
@app.before_first_request
def init_db():
print("服务器启动,初始化数据库或其他资源")
# 请求处理后执行(前提是没有未处理异常)
@app.after_request
def after_request_func(response):
print("请求处理完毕,返回响应")
return response
# 请求结束后执行(无论是否有异常)
@app.teardown_request
def teardown_request_func(exception=None):
print("请求结束,清理资源")
g 是钩子与视图之间共享数据的桥梁

2.8.5 响应
元组形式 (响应体, 状态码, 首部字典)




status_code

headers



常用头部content-type/length

Cookie 与缓存头的区别,Cache-Control / Expires
Cookie = 你的身份小纸条 → 给服务器看
Cache-Control/Expires = 页面缓存标签 → 给浏览器看

cookie

Cache-Control / Expires 记录这个页面可以缓存多久



不是所有头部都需要手动添加

Authorization,token
token是什么?客户端证明自己身份的"通行证"。证明自己可以访问服务端。服务端根据它来判断你能不能访问接口

token 在哪里携带?
headers(最常用,最安全)

Authorization(授权),HTTP 请求头(Header)的一种,它的作用是 告诉服务器"我是谁"或者"我有权限"。服务器根据它来判断你能不能访问接口。
HTTP 规定:如果你要验证身份,可以放在 Authorization 里
Authorization 的基本格式,Authorization: , → 认证方式/类型, → 认证凭证/证明内容。告诉服务器 后面的凭证怎么解析、怎么验证.身份证明的内容



Basic 的凭证 就是用户名和密码的 Base64 编码.

Bearer 的凭证 通常是 JWT,也可以是其他 token 类型


url参数(不安全)

cookie, 用户登录网站,服务器会把 token 放到 Cookie 里,浏览器收到后,每次访问同一网站(服务器),会 自动把这个 token 带上


什么时候 Cookie 不够?

cookie 和 token区别。token验证身份,cookie保存登录状态,偏好等

set_cookie(key, value, **options)。cookie 是服务器生成的,发送给浏览器的。浏览器负责保存和回传


下次访问同一网站(服务器) → 浏览器自动在请求里带上 cookie,满足域名,路径,未过期,自动在向这个服务器发送的所有请求中带上




set_cookie() 时,可以指定 cookie 生效的范围,主要是通过 domain(域名)和 path(路径) 来控制的



max_age 和 expires 都是过期时间,它们有什么区别


总结



delete_cookie(key, **options)


content_length

content_type

set_data(data)

字节流 就是 返回字节(bytes 类型),而不是普通字符串(str)

get_data(as_text=False)
字节流 就是 返回字节(bytes 类型),而不是普通字符串(str)

重定向

redirect

错误处理 abort()



无论在视图函数里,还是视图函数调用的其他函数里,只要 abort() 被调用,整个调用链都会中断,除非自己捕获了异常


只有在你显式用 try/except 捕获这个异常时,后续代码才会继续执行
