开发者网络

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 107|回复: 1

Python Web开发—Flask框架进阶—上下文、Flask扩展 ...

[复制链接]

1

主题

2

帖子

5

积分

新手上路

Rank: 1

积分
5
发表于 2023-1-18 18:27:06 | 显示全部楼层 |阅读模式
介绍了Django框架进阶(Python Web开发—Flask快速建站—Flask概述、路由详解、Jinja2模板、SQLAlchemy、WTForm表点),Flask框架以轻便、快捷的特点在Python Web开发中名列前茅。上一章主要讲解了Flask的安装及一些重要模块,本文将讲解本地线程、应用上下文、请求上下文、Flask-Script、Flask-DebugToolbar、Flask-Admin,下面将介绍Flask-Migrate、Flask-Cache、循环引用、常用数据结构、功能函数、加密、中间件。
Flask进阶之上下文
Context上下文
上下文的概念大多出现在文章中,表示语言的环境,上下文是属性的有序序列,为驻留在环境内的对象定义环境。在对象的激活过程中创建上下文,对象被配置为某些自动服务,如同步、事务、实时激活、安全性等。Flask中主要有两种上下文:应用上下文(Application Context)和请求上下文(Request Context)。具体内容如下:
application是当调用app = Flask(__name__)时创建的对象app。
request是每次HTTP请求发生时,WSGI server调用Flask.call()之后,在Flask对象内部创建的Request对象。
application表示用于响应WSGI请求的应用本身,request表示每次HTTP请求。
application的生命周期大于request,一个application存活期间,可能发生多次HTTP请求,因此也会有多个request。
接下来讲解本地线程和上述两种上下文。
Ø 本地线程
对象是保存状态的地方,在Python中,一个对象的状态都被保存在对象携带的一个字典中,ThreadLocal则是一种特殊的对象,它的“状态”对线程隔离(每个线程对一个ThreadLocal对象的修改都不会影响其他线程)。这种对象的实现原理非常简单,只要以线程的ID来保存多份状态字典即可,就像按照门牌号隔开的一格一格的信箱,因此只要有ThreadLocal对象,就能让同一个对象在多个线程下做到状态隔离。
Flask是一个基于WerkZeug实现的框架,因此Flask的Application Context和Request Context是基于WerkZeug的Local Stack的实现。这两种上下文对象类定义在flask.ctx中,ctx.push会将当前的上下文对象压栈压入flask._request_ctx_stack中,这个_request_ctx_stack同样是个ThreadLocal对象,也就是在每个线程中都不一样,上下文压入栈后,再次请求时都是通过_request_ctx_stack.top在栈的顶端提取,所取到的永远是属于自己线程的对象,这样不同线程之间的上下文就做到了隔离。请求结束后,线程退出,ThreadLocal本地变量也随即销毁,然后调用ctx.pop()弹出上下文对象并回收内存。
Ø 应用上下文
当一个Flask App读入配置信息并启动,就进入了应用上下文,在其中,开发人员可以访问配置文件、打开资源文件、通过路由规则反向构造URL。
在应用上下文中含有两个全局变量:
current_app:当前激活程序的实例对象。
g:处理请求时用作临时存储的对象,每次请求都会重设这个变量。
接下来讲解应用上下文的使用,具体示例如下:


在上述示例中,可以通过current_app.name来获取当前应用的名称,也就是__name__;current_app是一个本地代理,它的类型是werkzeug.local. LocalProxy,它所代理的是app对象,也就是说current_app == LocalProxy(app)。使用current_app是因为它也是一个ThreadLocal变量,对它的改动不会影响到其他线程。通过current_app._get_current_object()方法可以获取app对象。current_app只能在请求线程里存在,因此它的生命周期也是在应用上下文里,离开应用上下文无法使用。
若想直接打印出current_app.name可显式调用app_context()方法实现,具体示例如下:


在上述示例中,app_context()方法会创建一个AppContext类型对象,即应用上下文对象,此后就可以在应用上下文中访问current_app对象了。
Ø 请求上下文
在Flask中处理请求时,应用会生成一个“请求上下文”对象,整个请求的处理过程都会在这个上下文对象中进行,保证请求的处理过程不被干扰,具体示例如下:


Flask的request对象只有在其上下文的生命周期内才有效,离开了请求的生命周期,其上下文环境就不存在了,也就无法获取request对象。Flask中有四种请求hook(钩子)函数,分别是@before_first_request 、@before_request 、@after_request、 @teardown_request,这四种hook函数会挂载在生命周期的不同阶段,因此在其内部都可以访问request对象。
与应用上下文类似,请求上下文可以通过Flask的内部方法request_context()来构建一个请求上下文,具体示例如下:


在上述示例中,request_context()会创建一个请求上下文RequestContext类型的对象,需接收Werkzeug中的environ对象为参数。Werkzeug是Flask所依赖的WSGI函数库。
上述示例还可以通过with关键字进行简化,具体示例如下:


Flask扩展
使用Flask框架可以高效、便捷地编写程序,原因在于Flask框架有很多实用性强的扩展。如前面章节讲解的Django框架扩展,在实际开发中可以直接使用,开发者无须从零开始编写;同样地,在Flask框架中也包含许多扩展包。接下来讲解Flask框架中的常用扩展包,主要有Flask-Script、Flask-DebugToolbar、Flask-Migrate、Flask-Security、Flask-RESTful、Flask-Admin、Flask-Cache、蓝本、循环依赖以及表单的相关扩展。
Ø Flask-Script
Flask-Script扩展提供向Flask插入外部脚本的功能,包括运行开发用的服务器、定制Python shell、设置数据库脚本cronjobs以及其他的运行在Web应用之外的命令行任务。
Flask-Script和Flask本身的工作方式类似,只需要定义和添加能从命令行中被Manager实例调用的命令即可,接下来讲解Flask-Script的使用。
(1)安装Flask-Script,使用PyCharm(不再赘述)或pip命令安装。命令如下:


注意:本章都是使用PyCharm安装插件。
(2)创建hello.py文件,并使用Flask-Script来编写代码,如例所示。


上述代码中,第2行从flask_script中引入Manager(Flask-Script扩展中的内容);第4行将Manager(app)赋值给manager;第11~12行启动Flask-Script扩展服务器。
(3)在PyCharm的【Terminal】中输入以下命令查看相关结果:


上述代码运行hello.py并监听127.0.0.1上的连接,其中--host参数是web服务器监听的网络接口,用来监听来自客户端的连接,由于代码是使用Flask框架编写,因此默认端口号为5000,然后在浏览器中输入http://127.0.0.1:5000/查看结果,结果如图所示。


在浏览器中输入http://127.0.0.1:5000/user/小千,运行结果如图所示。


Ø Flask-DebugToolbar
Django中有非常著名的调试工具——Django-DebugToolbar,Flask中也有对应的替代工具——Flask-DebugToolbar,接下来讲解Flask-DebugToolbar的使用。
(1)安装Flask-DebugToolbar,使用PyCharm(不再赘述)或pip命令安装,命令如下所示:


(2)安装好后在flask1.py文件(创建项目时生成的文件)中编写代码,使用Flask-DebugToolbar,如例所示。


上述代码中,第2行是从flask_debugtoolbar中引入DebugToolbarExtension扩展;第5行是将debug的值设置为True,只有当debug值为True时才能使用调试工具,但一般只在调试模式下使用,在生产环境下将debug的值设置为False;第6行是设置SECRET_KEY;第7行是将调试工具绑定应用app。
注意:第10行和第13行中HTML标签至少包含<body></body>。
(3)接着运行服务器(调试模式),并在浏览器中输入http://localhost:5000/,运行结果如图所示。


在浏览器中输入http://localhost:5000/user/小锋,运行结果如图所示。


图右侧的工具栏即是调试工具栏,调试工具栏的使用可以极大的提高开发效率,并且使代码编写的准确性大大提高。
注意:localhost与127.0.0.1都代表本机地址。
调试工具栏还支持多个配置选项,具体配置项如表示。


若要更改配置选项,在 Flask 应用程序中配置,具体示例如下:


Ø Flask-Admin
Django中直接提供了Admin站点管理,在Flask中可以通过Flask-Admin扩展来实现后台管理。接下来讲解Flask-Admin的使用。
(1)安装Flask-Admin,使用PyCharm(不再赘述)或pip命令安装,命令如下所示:


(2)创建admin.py文件,并编写后台管理代码,如例所示。


上述代码中,第2行是从flask-admin中引入Admin模块;第4行实例化一个Admin,name为‘后台管理系统’。
(3)使用命令“python admin.py runserver”在浏览器中输入http://localhost:5000/admin/,运行结果如图所示。


后期可以根据项目的需要在后台管理页面中添加视图、模板、数据库数据等相关内容,最终实现管理后台的目的。
Ø Flask-Migrate
在实际的开发环境中,经常会发生数据库修改行为,一般不会手动地去修改数据库的数据,而是去修改ORM对应的模型,然后再把模型映射到数据库中,Flask-Migrate可以很好地完成这部分操作。Flask-Migrate是基于Alembic进行的一个封装,并集成到Flask中,所有的迁移操作都是Alembic做的,它能跟踪模型的变化,并将变化映射到数据库中,接下来讲解Flask-Migrate的使用。
(1)安装Flask-Migrate,使用PyCharm(不再赘述)或pip命令安装,命令如下所示:


(2)要让Flask-Migrate能够管理App中的数据库,需要使用Migrate(app,db)来绑定app和数据库,具体示例如下:


上述示例通过绑定相应的App以及数据库来对数据库中数据进行操作,其中“manager.add_command('db', MigrateCommand)”表示在flask-script中添加一个db命令,用于操作数据库。
使用Flask-Migrate
通过命令“python manager.py db init”来创建迁移仓库,命令“python manager.py db migrate -m "initial migration"”是用来创建迁移脚本,即在数据库结构有变动后创建迁移脚本,使用命令python manager.py db upgrade来更新数据库。

Ø Flask-Cache
当同一个请求被多次调用,每次调用都会消耗大量资源,并且每次返回的内容都相同时应该考虑使用缓存,对于大型互联网应用,合理运用缓存可使应用的性能成几何级数地上升,Flask中有专门处理缓存的扩展包,接下来讲解Flask缓存扩展——Flask-Cache的使用。
(1)安装Flask-Cache,使用PyCharm(不再赘述)或pip命令安装,命令如下所示:


(2)接下来以一个简单的实例来讲解Flask-Cache的使用,如例所示。


上述代码是使用Flask-Cache扩展将缓存技术实现。第2行是从flask_cache扩展中导入Cache;第4行是使用了simple类型缓存,其内部实现就是Werkzeug中的SimpleCache,也可以使用第三方缓存服务器,如Redis;第5行是使用cache.cached()函数将缓存设置装饰到get_list()函数上,设置缓存过期时间是50秒,cache.cached()函数不仅可以装饰普通函数,还可以装饰视图函数;第6~8行是get_list()函数定义;第9行是路由设置;第10~11行是list()函数定义。
接下来运行项目,并在浏览器中输入http://127.0.0.1:5000/list,控制台的显示结果如图所示。


浏览器中显示结果如图所示。


第二次刷新网址浏览器中显示与图相同,但控制台中显示如图所示。



Ø 循环引用
在Web的开发中经常会遇到循环引用的情况,接下来以一个示例来讲解循环引用,具体示例如下:
models.py


server.py


上述示例就会出现循环引用问题,在models.py中直接引用了server.py中的内容,又在server.py中直接引用models.py中的内容,因此出现循环引用问题。循环引用的解决方法有以下几种:
(1)延迟导入。把import语句写在方法或函数里面,将它的作用域限制在局部,这种方法的缺点就是会有性能问题。
(2)将from xxx import yyy改成import xxx;xxx.yyy来访问的形式
(3)组织代码。
出现循环引用的问题往往意味着代码的布局有问题,可以将竞争资源进行合并或者分离。合并是将内容都写到一个文件里面去,分离是将需要导入的资源提取到第三方文件中,最终实现将循环变成单向。
Flask框架中还有很多第三方扩展。例如,集成了Bootstrap的Flask-Bootstrap,使用Flask-restful来构建RESTful API,使用Flask-Principal实现角色的权限管理等,灵活使用这些第三方框架,可以轻松完成网站中的各种功能。
Werkzeug的使用
Flask框架简介中讲解了Werkzeug的概念及特性。Werkzeug是Python的WSGI规范的实用函数库,本节主要讲解Werkzeug的使用。
在使用Werkzeug之前先安装Werkzeug,使用PyCharm(不再赘述)或pip命令安装,命令如下所示:


在命令提示符中安装成功界面如图所示。


Ø 常用数据结构
在开发和工作中经常会使用到各种数据结构,数据结构的内容比较复杂,个人编写会消耗大量时间而且数据处理的效率可能达不到要求;而在Werkzeug中提供了多种数据结构,正好解决上述问题,接下来讲解常用的几种数据结构。
1. TypeConversionDict:
继承于dict,通过执行其中的get方法来指定值的类型,具体示例如下:


运行结果如图所示。


2. ImmutableTypeConversionDict:
不可变的TypeConversionDict。
3. MultiDict:
继承自TypeConversionDict,可以对相同的键传入多个值,并把这些值保留下来,具体示例如下:


运行结果如图所示。


4. ImmutableMultiDict:
不可变的MultiDict。
5. OrderedMultiDict:
继承自MultiDict,但保留了字典的顺序。
6. ImmutableOrderedMultiDict:
不可变的OrderedMultiDict。
Ø 功能函数
在Werkzeug还提供了一些十分有用的功能函数,接下来讲解其中三个比较常用的函数。
1. cached_property:
著名装饰器,通过描述符把方法执行的结果作为一个属性(property)缓存下来,具体示例如下:


上述示例使用了cached_property装饰器,将函数qf()的执行结果进行缓存,之后在执行该函数的时候直接返回结果,而不再执行该函数,如所示。


2. import_string:
通过字符串直接找到对应模块,具体示例如下:


运行结果如图所示。


3. secure_filename:
返回一个安全版本的文件名,具体示例如下:


运行结果如图所示。


使用功能函数可以很方便地实现一些特定的功能,这在实际开发过程中都是很重要的。灵活运用功能函数,使开发达到事半功倍的效果。

Ø 加密
在现实生活中,用户登录网站时会发现密码是不可见的,而且在网站的数据库中查看密码也是一串“乱码”,即被加密之后的密码,因为密码是重要(隐私)字段,不能使用明文存储,需要对其加密之后再存储。Web开发中常用的加密方法是加盐哈希加密,即在加密时添加一些随机字符(盐值,salt),然后再进行哈希加密(如MD5,SHA1等)。这样处理的结果可以使得即使密码相同,添加的盐值不同,最终的哈希值也不一样。Werkzeug中提供了密码加盐的哈希函数,具体示例如下:


运行结果如图所示。


Ø 中间件
在Django进阶一章中详细讲解了Django的中间件,中间件主要是用来记录日志、会话管理、请求验证、性能分析等工作的,Werkzeug中提供了10个中间件,本小节主要讲解常用的3个中间件。
1. SharedDataMiddleware
SharedDataMiddleware是提供一个静态文件分享(下载)的路由,它和Flask中默认的static不同,Flask是利用send_file来控制静态文件,而SharedDataMiddleware可以直接在app里注册相关的路由,绑定一个磁盘路径,并分享这个路径下的文件,具体示例如下:


上述示例运行之后,若程序所在目录的static下有一个名为qianfeng.js的文件,可以通过http://localhost:9000/static/qianfeng.js来访问。
2. ProfilerMiddleware
ProfilerMiddleware是一个添加性能分析的中间件,它会在profile_dir下写入访问页面的程序运行状况,包括执行的函数以及运行时间等,具体示例如下:


上述示例运行之后并在浏览器中输入http://127.0.0.1:9000/,结果如图所示。


浏览器执行完后,PyCharm中【Terminal】中显示结果,如图所示。


3. DispacherMiddleware
DispatcherMiddleware是可以向一个app注册其他 app的中间件,即可以调度多个应用的中间件,具体示例如下:


编写完上述示例后,访问以/app2为前缀的url时会使用app2的相关逻辑,app3同理。
小结:Python Web开发—Flask框架进阶—上下文、Flask扩展、Werkzeug的使用
主要讲解Flask框架中的一些高级内容,包括Context上下文、Flask扩展、Werkzeug的使用三部分内容。对于本内容,大家应当多在实际开发中进行探索使用,并达到熟练于心的状态。
回复

使用道具 举报

0

主题

4

帖子

7

积分

新手上路

Rank: 1

积分
7
发表于 2025-5-26 04:30:18 | 显示全部楼层
1v1飘过
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|开发者网络

GMT+8, 2025-6-7 12:37 , Processed in 0.092490 second(s), 23 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表