读《Flask Web开发实战》(狼书)笔记 | 第1、2章
前言
2023-8-11
以前对网站开发萌生了想法,又有些急于求成,在B站照着视频敲了一个基于flask的博客系统。但对于程序的代码难免有些囫囵吞枣,存在许多模糊或不太理解的地方,只会照葫芦画瓢。
而当自己想开发一个什么网站的时,就如同摸着石头过河,常在许多小问题上卡住,不知怎么实现,也不知道需要去学习什么才能实现。例如,要做一个聊天室程序,我却不知道在一方发出消息时,如何在另一方实时地显示出来,思虑许久而终归于放弃。
学习系统且详细的知识有其好处,它可以冲退我那种徒手在黑暗中摸索的感觉。读了“狼书”的两个章节,自觉很有收获,此前的许多疑惑也得到了解答。然凡事各有弊益,啃书不是易事,还需下苦功夫。
曾有人对我说,看视频会更有效率。也许他是对的?但我好像更喜欢书籍给我的感觉。但有些讽刺的是,大学至今,我却也没看下来多少书,而时间在我休息的时候,它仍努力奔跑,两载一晃而过。而不少人,也是这相似的困境吧?
回到本文,它是一篇读书笔记,参杂少许个人想法但含量不高,所记零散,主要是作为个人提纲备忘,或许对诸位而言阅读价值不高。若想学习 Flask 框架,我还是很推荐去读“狼书”原著的。
文章目录
- 前言
- 开始
- Git使用
- 1 初识Flask
- 1.1 搭建开发环境
- 1.2 简单示例
- 2 Flask与HTTP
- 2.1 重定向回上一个页面
- 2.2 使用AJAX技术发送异步请求
- 2.3 HTTP服务器推送
- 2.4 Web安全防范
开始
5个难度递增的案例:留言板SayHello,个人博客Bluelog,图片社交网站Albumy,待办事项程序Todoism,聊天室CatChat。
前端学习:
Web很多程序离不开javascript,它可以方便、简洁地实现很多页面按逻辑和功能。
了解Git:https://try.github.io/
文本编辑器:
作者的博客:http://greyli.com
Git使用
克隆本书代码仓库:
git clone https://github.com/greyli/helloflask.git
查看当前项目仓库中包含的所有标签:
git tag -n
签出对应标签版本的代码:
git checkout foo
签出前对文件做了修改,需要撤销:
git reset --hard
使用diff命令比较两个标签对应版本之间的变化:
git diff foo bar
使用git客户端直观查看版本变化:
gitk
定期使用git fetch命令来更新本地仓库:
git fetch --all
git fetch --tags
git reset --hard origin/master
在本地复制新的派生仓库,后可以在本地自由修改其中的代码:
git clone https://github.com/你的用户名/helloflask.git
1 初识Flask
Web框架可以让我们不用关心底层的请求响应处理,更方便地编写Web程序。
两个主要依赖:(p3)
- WSGI(Web Server Gateway Interface,Web服务器网关接口)的工具集——Werkzeug(http://werkzeug.pocoo.org/)
- Jinja2模板引擎
1.1 搭建开发环境
Pipenv:pip的加强版,让包安装、包依赖管理、虚拟环境管理更加方便。
创建虚拟环境:在项目根目录(即helloflask文件夹中),使用pipenv install
命令。Pipfile
文件列出的依赖包也会一并被安装。
显示激活虚拟环境:Pipenv会自动从项目目录下的.env
文件中加载环境变量。
# 激活
pipenv shell
# 退出
exit
临时使用虚拟环境中的python解释器:(更推荐)
pipenv run python hello.py
查看当前环境下的依赖情况:
pipenv graph
关于Pipfile项目的更多情况,请访问其主页。
使用
pipenv install
命令安装包时,都是安装到虚拟环境中。相当于使用pip在激活虚拟环境的情况下安装包。
更新flask版本:(书中为flask-1.0.2)
pipenv update flask
集成开发环境:pycharm专业版提供了更多针对Flask开发的功能,比如创建Flask项目模板,Jinja2语法高亮,与Flask命令行功能集成等。
设置Python解释器(好像已经不需要了):因为PyCharm未集成支持Pipenv。(p10)
1.2 简单示例
from flask import Flask
app = Flask(__name__)@app.route('/')
def index():return '<h1>Hello Flask!</h1>'
Flask类表示一个Flask程序,实例化这个类就得到了我们的程序实例app。__name__
对于文件app.py而言,值即为“app”,它帮助Flask在相应的文件夹里找到需要的资源,比如模板和静态文件。(p12)
注册路由:路由负责管理URL和函数之间的映射。
- 一个视图函数可以绑定多个路由。
- 动态路由:可以传递参数,并可设置默认参数。
注:Flask内置一个开发服务器,但在实际生产环境中需要使用性能更好的生产服务器。
启动开发服务器:
# 未启动虚拟环境下使用
pipenv run flask run
# 在虚拟环境中
flask run
# 命令未找到
python -m flask run
app.run()
方法也可启动开发服务器,已经不推荐使用。
flask寻找程序实例:
- 在当前目录下,名为
app.py
或wsgi.py
的文件中寻找名为app
的程序实例。 - 根据环境变量FLASK_APP寻找。
# 在linux
$ export FLASK_APP=hello
# 在windows
> set FLASK_APP=hello
管理环境变量:使用python-dotenv
包,从.env
或.flaskenv
文件加载。其中.env
文件存放一些敏感数据。
pipenv install python-dotenv
可在.flaskenv
写入:
# 默认为production(生产环境),开发模式将打开调试器和重载器。
FLASK_ENV=development
使用Pycharm的运行配置(而不使用命令行):在Run --> Edit Configurations(p19)
使服务器外部可见:让局域网用户可以通过你的内网IP进行访问。想要公网访问,可以考虑内网穿透工具、端口转发工具等,如 ngrok、Localtunnel。
flask run --host=0.0.0.0
flask的环境变量:可通过FLASK_<COMMAND>_<OPTION>
设置各种选项。
重载器:安装 Watchdog。Werkzeug内置有stat重载器,但耗电严重且准确性一般。
# dev: 开发依赖的包
pipenv install watchdog --dev
打开PythonShell:使用flask打开的shell自动包含程序上下文,并且已经导入了app实例。
flask shell
Flask扩展:使用Flask提供的接口编写的Python库。扩展可以加速开发,但也会降低灵活性,并可能存在bug。
Flask项目配置:可能用到Flask提供的配置、扩展提供的、程序特定的配置。它们用Flask对象的app.config属性作为统一的接口。
- Flask配置章节:https://flask.pocoo.org/docs/latest/config/
app.config['ADMIN_NAME'] = 'Peter'
# 一次加载多个值
app.config.update()方法
URL:使用url_for()
,方便url规则的修改。
- 相对url与绝对url(p24)
自定义Flask命令:
- Click官方文档(自定义命令):http://click.pocoo.org/6/
@app.cli.command()
def hello():click.echo('Hello, Human!')
> flask hello
Hello, Human!
视图函数之名:可以溯源至MVC架构,即”模型 - 视图 - 控制器”。但flask并不是MVC架构的框架,因为没有内置数据模型的功能(需使用扩展),视图函数成为控制器函数才更加合适。(p28)
2 Flask与HTTP
request对象常用的属性和方法:(p43)
Response类常用属性和方法:(p48)
查看路由列表:这个列表由app.url_map
解析得到。其中static为Flask添加的特殊路由,用来访问静态文件。
> flask routes
Flask内置的URL变量转换器:(p37)
URL规则中的转换器:<转换器:变量名>
,
@app.route('goback/<int:year>')
def go_back(year):return '<p>Welcome to %d!</p>' % (2018 - year)
请求钩子:也称回调函数,可以用来注册在请求处理的不同阶段执行的处理函数,如预处理、后处理,它们使用装饰器 实现。(p58)
响应:大多数情况下,我们只负责返回响应的主体内容(而不负责首部及各种字段)。Flask会调用make_response()
方法将视图函数返回值转换为响应对象。当然,响应也可以包含响应主体、状态码、首部字段 三个部分内容。
可使用redirect(<url字符串>)
方法重定向。
@app.route('/')
def hello_flask():return '', 302, {'Location':'https://www.baidu.com'}
注:状态码不可儿戏,如将上面的
302
改为202
,则重定向会失效。
错误响应:在视图函数中使用abort(<状态码>)
,例如:
@app.route('/404')
def not_found():abort(404)
响应格式:在 HTTP 响应中,数据可以通过多种格式传输,默认为 HTML。可以设置不同的 MIME 类型来标识不同的数据格式,MIME 类型在 Content-Type 字段中定义。
# method 1 - 修改响应对象的属性
# @plain 纯文本
from flask import make_response
...
response = make_response("hello")
response.mimetype = 'text/plain'
# method 2 - 设置首部字段
response.headers['Content-Type'] = 'text/html; charset=utf-8'
-
XML:
application/xml
,一般作为 AJAX 请求的响应格式,或是 Web API 的响应格式。 -
JSON:
application/json
,指 JavaScript Object Notation(JavaScript对象表示法),更轻量、易解析。json模块的dumps()方法,可以将python中的字典、列表、元组数据序列化为json字符串。
# 1 - python标准库的json模块
response = make_response(json.dumps(data))
response.mimetype = 'application/json'
return response
# 2 - 使用flask包装的jsonify()函数
return jsonify(data)
Cookie:HTTP 是无状态协议。Cookie是保存在浏览器上的小型文本数据,保存一定时间,在下一次向同一个服务器发送请求时附带这些数据。但明文存储存在安全隐患。
使用set_cookie()
方法设置(参数见p68),从cookies
属性获取。
Session:在Flask中,session对象用来存储加密的cookie。
- 设置程序密钥:通过
Flask.secret_key
属性;或环境变量SECRET_KEY
(可保存在.env
文件),在脚本中通过getenv()
方法获取。
import os
app.secret_key = os.getenv('SECRET_KEY', 'secret string')
疑问:写进了环境变量还需再脚本中手动获取?那我随便用个环境变量名称是不是也可以?
疑问:看不懂:使用session对象存储的Cookie,用户可以看到其加密后的值,但无法修改它。因为session中的内容使用密钥进行签名,一旦数据被修改,签名的值也会变化。这样再读取时,就会验证失败,对应的session值也会失效。 (p51)
- session cookie的保存时间:
上下文:Flask中有两种上下文:程序上下文 和请求上下文 。
两种上下文在视图函数中都会自动激活,这也意味折一些依赖于上下文的函数只能在视图函数中使用,如url_for()
、jsonify()
等。
也可手动激活程序上下文:
>>> from app import app
>>> from flask import current_app# 方法1
>>> with app.app_context():... current_app.name# 方法2
>>> app_ctx = app.app_context()
>>> app_ctx.push()
>>> current_app.name
>>> app_ctx.pop()# 激活请求上下文类似
>>> from app import app
>>> from flask import request
>>> with app.test_request_context('/hello'):...
疑惑:g、request等对象如何区分不同的客户端?
上下文钩子:使用它注册的回调函数会在程序上下文被销毁时调用。
@app.teardown_appcontext
def teardown_db(exception):...db.close()
2.1 重定向回上一个页面
利用referrer或URL的查询参数。(p59)
referrer:即访问来源。当用户在某个站点单击链接,浏览器向新链接所在的服务器发起请求,请求的数据中包含的HTTP_REFERER字段记录了用户所在的原站点URL。
疑惑:书中判断url是否安全的代码(如下)使我困惑了许久:既然
test_url
中也与request.host_url
做了拼接,那最后的netloc
不是必然相同吗?后来我查找了
urljoin(base, url)
函数的处理机制:
- 如果
url
是一个相对URL,那么urljoin
会从url
中获取路径部分,并于base
中获取的部分合并;- 如果
url
是一个绝对URL,则urljoin
会直接返回url
。那么在什么情况下,
is_safe_url
函数的返回值才为False
呢?
- 首先,
target
是一个绝对URL。- 同时,该绝对URL的协议或主机不是本机。
综上,还是感觉该函数的逻辑写得有些隐晦了,不便于理解(肯定不能是我太笨)。
def is_safe_url(target):ref_url = urlparse(request.host_url)test_url = urlparse(urljoin(request.host_url, target))return test_url.scheme in ('http', 'https') and \ref_url.netloc == test_url.netloc
2.2 使用AJAX技术发送异步请求
jQuery中和AJAX相关的方法和具体用法:http://api.jquery.com/category/ajax/
前言
在传统的Web应用中,程序的操作都是基于请求响应循环来实现的。每当页面状态需要变动,或是需要更新数据时,都伴随折一个发向服务器的请求。当服务器响应时,整个页面会重载,并渲染新页面。
频繁更新页面会牺牲性能,且影响用户体验。
AJAX是指异步Javascript和XML(Asynchronous JavaScript And XML),是一系列技术的组合体,如XMLHttpRequest、JavaScript、DOM。它让Web程序更像是程序,而非一堆用链接和按钮链接起来的网页资源。
可以使用 jQuery 实现AJAX操作:函数ajax()
可以发送AJAX请求。
2.3 HTTP服务器推送
推送技术对比:https://stackoverflow.com/a/12855533/5511489
- 传统轮询
- 长轮询
- SSE(Server-Sent Events)
- Websocket
2.4 Web安全防范
OWASP(Open Web Application Security Project,开放式Web程序安全项目):https://www.owasp.org 。(p66)
常见攻击方式:
- 注入攻击
- XSS攻击(Cross-Site Scripting,跨站脚本):将代码注入被攻击者的网站
- CSRF攻击:(Cross Site Request Forgery,跨站请求伪造):伪造用户的登陆状态。
提示:虽然在实际开发中,通过在”删除“按钮中加入链接来删除资源非常方便,但安全问题应该作为编写代码时的第一考量,应该将这些按钮内嵌在使用了POST方法的form元素中。攻击者就无法通过GET请求来修改用户的数据。
疑惑:未理解csrf攻击的防御原理。
相关文章:

读《Flask Web开发实战》(狼书)笔记 | 第1、2章
前言 2023-8-11 以前对网站开发萌生了想法,又有些急于求成,在B站照着视频敲了一个基于flask的博客系统。但对于程序的代码难免有些囫囵吞枣,存在许多模糊或不太理解的地方,只会照葫芦画瓢。 而当自己想开发一个什么网站的时&…...

Tomcat+Http+Servlet
文章目录 1.HTTP1.1 请求和响应HTTP请求:请求行请求头请求体HTTP响应:响应行(状态行)响应头响应体 2. Apache Tomcat2.1 基本使用2.2 IDEA中创建 Maven Web项目2.3 IDEA中使用Tomcat 3. Servlet3.1 Servlet快速入门3.2 Servlet执行…...

Leaflet入门,Leaflet如何实现vue双向绑定数据添加到图片标记物到地图上,动态根据vue数据更新到地图上以及鼠标经过标记物显示提示框
前言 本章使用Leaflet的vue2-leaflet或者vue-leaflet插件方式实现vue数据绑定地图数据,实现地图标记物与vue数据的双向联动更新,以及鼠标经过标记物显示提示框功能。 实现效果演示 vue如何使用Leaflet vue2如何使用:《Leaflet入门,如何使用vue2-leaflet实现vue2双向绑定…...
C++设计模式结构型之代理模式
一、概述 代理模式是一种结构型模式,在很多不同的场合具有广泛的分类和应用。其主要实现的思想是在客户端和真正要访问的对象之间引入一个 代理对象(间接层),于是,以往客户端对真正对象的访问现在变成了通过代理对…...
使用PHP实现实时聊天功能的匿名聊天与加密传输
使用PHP实现实时聊天功能的匿名聊天与加密传输 随着互联网的发展,人与人之间的交流方式也发生了天翻地覆的变化。其中,实时聊天功能成为了一种越来越受欢迎的交流方式。对于很多网站来说,提供匿名聊天功能能够吸引更多的用户参与,…...

Maven 基础之依赖管理、范围、传递、冲突
文章目录 关于依赖管理坐标和 mvnrepository 网站pom.xml 中"引"包 依赖范围依赖传递依赖冲突 关于依赖管理 坐标和 mvnrepository 网站 在 maven 中通过『坐标』概念来确定一个唯一确定的 jar 包。坐标的组成部分有: 元素说明<groupId>定义当前…...
Python jupyter lab 设置
在下载好jupyter lab 后,需要对其进行设置,尤其是远程服务器的时候,因为根本就是没有屏幕,也没有浏览器。 新建设置文件 jupyter lab --generate-config设置文件内部参数 vim ~/.jupyter/jupyter_lab_config.py进去一通改&#…...

水库大坝安全监测系统实施方案
一、方案概述 水库大坝作为特殊的建筑,其安全性质与房屋等建筑物完全不同,并且建造在地质构造复杂、岩土特性不均匀的地基上,目前对于大坝监测多采用人工巡查的方法,存在一定的系统误差,其工作性态和安全状况随时都在变…...

GloVe、子词嵌入、BPE字节对编码、BERT相关知识(第十四次组会)
GloVe、子词嵌入、BPE字节对编码、BERT相关知识(第十四次组会) Glove子词嵌入上游、下游任务监督学习、无监督学习BERTGlove 子词嵌入 上游、下游任务 监督学习、无监督学习 BERT...

Debian10:安装PHPVirtualBox
PHPVirtualBox 是一个用 PHP 编写,用于管理 VirtualBox 的 Web 前端(由AJAX实现)。 参考文章:VirtualBoxPHPVirtualBox部署_骡子先生的博客-CSDN博客php virualbox,浏览器远程控制VBox 虚拟机phpVirtualBox_weixin_39815879的博客…...
RANSAC算法
RANSAC简介 RANSAC(RAndom SAmple Consensus,随机采样一致)算法是从一组含有“外点”(outliers)的数据中正确估计数学模型参数的迭代算法。 “外点”一般指的的数据中的噪声,比如说匹配中的误匹配和估计曲线中的离群点。所以,RANSAC也是一种“外点”检…...

考研408 | 【计算机网络】 传输层
导图 传输层的功能 传输层的两个协议 传输层的寻址与端口 UDP协议 UDP的主要特点 UDP首部格式: UDP校验: TCP协议 TCP协议的特点 TCP报文段首部格式 TCP连接管理 TCP的连接建立 SYN洪泛攻击 TCP的连接释放 TCP可靠传输 序号: 确认࿱…...
Redis_缓存3_缓存异常(数据不一致、雪崩、击穿、穿透)
14.6缓存异常 四个方面 缓存中数据和数据库不一致缓存雪崩缓存击穿缓存穿透 14.6.1数据不一致: 一致性包括两种情况 缓存中有数据,需要和数据库值相同缓存中没有数据,数据库中的数据是最新值 如果不符合以上两种情况,则出现…...
谁能讲清楚Spark之与MapReduce的对比
我们已经知道Spark是如何设计和实现数据处理流程的,这里我们 再深入思考一下,为什么Spark能够替代MapReduce成为主流的大数据处理框架呢?对比MapReduce,Spark究竟有哪些优势? 一 优势 1 通用性: 基于函数式编程思想,MapReduce将数据类型抽象为,k,v格式,并将数据处理…...

Android自定义侧滑Item
源码地址:https://github.com/LanSeLianMa/CustomizeView/tree/master/cehuaitem 使用方式一:XML布局中直接使用 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com…...

c++11 标准模板(STL)(std::basic_stringbuf)(三)
定义于头文件 <sstream> template< class CharT, class Traits std::char_traits<CharT>, class Allocator std::allocator<CharT> > class basic_stringbuf : public std::basic_streambuf<CharT, Traits> std::basic_stringbuf…...
Nodejs 第九章(模块化)
Nodejs 模块化规范遵循两套一 套CommonJS规范另一套esm规范 CommonJS 规范 引入模块(require)支持四种格式 支持引入内置模块例如 http os fs child_process 等nodejs内置模块支持引入第三方模块express md5 koa 等支持引入自己编写的模块 ./ …/ 等支…...

shell之正则表达式及三剑客grep命令
一、正则表达式概述 什么是正则表达式? 正则表达式是一种描述字符串匹配规则的重要工具 1、正则表达式定义: 正则表达式,又称正规表达式、常规表达式 使用字符串描述、匹配一系列符合某个规则的字符串 正则表达式 普通字符: 大小写字母…...
LeetCode 热题 100 JavaScript--33. 搜索旋转排序数组
整数数组 nums 按升序排列,数组中的值 互不相同 。 在传递给函数之前,nums 在预先未知的某个下标 k(0 < k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nums[1], …,…...

并发编程 - 线程池中的常见面试题
目录 1. 线程池相比于线程有什么优点 2. 线程池的参数有哪些 3. 线程工厂有什么用 4. 说一下线程的优先级 5. 说一下线程池的执行流程 6. 线程池的拒绝策略有哪些 7. 如何实现自定义拒绝策略 8. 如何判断线程池中的任务是否执行完成 1. 线程池相比于线程有什么优点 有…...

网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...

C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...

(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...
第7篇:中间件全链路监控与 SQL 性能分析实践
7.1 章节导读 在构建数据库中间件的过程中,可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中,必须做到: 🔍 追踪每一条 SQL 的生命周期(从入口到数据库执行)&#…...

mac:大模型系列测试
0 MAC 前几天经过学生优惠以及国补17K入手了mac studio,然后这两天亲自测试其模型行运用能力如何,是否支持微调、推理速度等能力。下面进入正文。 1 mac 与 unsloth 按照下面的进行安装以及测试,是可以跑通文章里面的代码。训练速度也是很快的。 注意…...