读《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. 线程池相比于线程有什么优点 有…...
从零到一:STM32 SPWM逆变器设计全流程解析
从零到一:STM32 SPWM逆变器设计全流程解析 在新能源和电力电子领域,逆变器作为直流转交流的关键设备,其设计能力已成为工程师的核心竞争力之一。而基于STM32的SPWM逆变器设计,因其高性价比和灵活可控的特点,正成为工业…...
从内存寻址到游戏操控:CE逆向分析扫雷核心机制的完整实践
1. 逆向工程入门:为什么选择扫雷作为CE分析对象 逆向工程听起来高大上,但入门其实可以从经典小游戏开始。扫雷作为Windows系统自带游戏,结构简单但机制完整,是学习内存分析的绝佳标本。我第一次用Cheat Engine(CE&…...
2025届必备的十大AI辅助写作平台解析与推荐
Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 现在处于主流地位的AI论文平台数量众多且种类繁杂,这里包含着:DeepSe…...
【12.MyBatis源码剖析与架构实战】9.1 ⼆级缓存的原理
二级缓存(L2 Cache)是计算机体系结构中的关键组件,位于一级缓存(L1)和主内存之间,用于弥合CPU与内存之间的速度差异。下面详细解析其原理,并配合流程图说明数据访问流程。 一、二级缓存的核心原理 1. 存储层次定位 L1缓存:极快(~1ns),极小(32-64KB),与CPU核心紧…...
新手福音:通过快马平台零代码基础玩转picoclaw机器人板
作为一个刚接触嵌入式开发的新手,拿到picoclaw控制器时既兴奋又忐忑。这块小小的板子能控制电机、读取传感器,但如何让它动起来却让我一头雾水。好在发现了InsCode(快马)平台,不需要从零开始啃文档,就能快速生成可运行的示例代码。…...
33.3%提及率,直接提及却为0%:张雪机车的AI搜索“假性存在”危机
一次小范围诊断,暴露了一个关键信号:品牌在AI生成答案中的“存在感”,远没有看起来那么安全。近日,张雪机车在国内大火,各大媒体都对张雪本人做了铺天盖地的报道。我们是做GEO(生成式搜索优化)服…...
股票相似K线匹配的Python实现:Tushare数据+皮尔逊相关系数全解析
股票相似K线匹配的Python实战:从数据获取到模式识别全流程 在量化交易领域,K线形态分析一直是技术派投资者的重要工具。传统的人工识别方法效率低下且主观性强,而借助Python和现代统计学方法,我们可以实现K线模式的自动化识别与匹…...
Boost电路与SMC滑模控制策略:文章复现及性能优化探讨
boost电路,smc滑模控制,文章复现Boost电路在电力电子里算是老熟人了,但真要玩转它的闭环控制可不容易。最近在复现一篇用滑模控制(SMC)搞Boost电路的论文,实测发现这货对付负载突变确实有两把刷子。今天咱们…...
7个实用技巧:用immich实现自托管相册智能管理 | 隐私保护与高效共享指南
7个实用技巧:用immich实现自托管相册智能管理 | 隐私保护与高效共享指南 【免费下载链接】immich High performance self-hosted photo and video management solution. 项目地址: https://gitcode.com/GitHub_Trending/im/immich 你是否曾在数千张照片中艰难…...
局域网聊天室终极解决方案:无需互联网的即时通讯工具
局域网聊天室终极解决方案:无需互联网的即时通讯工具 【免费下载链接】LAN-Chat-Room 😉基于QT开发的局域网聊天室 项目地址: https://gitcode.com/gh_mirrors/la/LAN-Chat-Room 在办公室、学校或家庭网络中,你是否曾遇到过需要快速分…...







