(Flask Web开发:基于Python的Web应用开发实战)------学习笔记(第2章)

第2章 程序的基本结构

本章将带你了解 Flask 程序各部分的作用,编写并运行第一个 Flask Web 程序。

2.1 初始化

  所有 Flask 程序都必须创建一个程序实例,程序实例是 Flask 类的对象。
  Web 服务器使用一种名为 Web 服务器网关接口(Web Server Gateway Interface,WSGI)的协议,把接收自客户端的所有请求都转交给这个对象处理。经常使用下述代码创建:

from flask import Flask
app = Flask(__name__)

  Flask 类的构造函数只有一个必须指定的参数,即程序主模块或包的名字__name__。不能传入整形值会报错,也不能传入标准模块名,会影响静态文件的访问,不会影响视图函数的访问。

__name__的作用
  
1>Flask 用这个参数决定程序的根目录,以便稍后能够找到相对于程序根目录的资源文件位置。
2>创建静态路由http://127.0.0.1:5000/static/,方便静态资源的访问。

2.2 路由和视图函数

  客户端(例如 Web 浏览器)把请求发送给 Web 服务器,Web 服务器再把请求发送给 Flask程序实例。程序实例需要知道对每个 URL 请求运行哪些代码,所以保存了一个 URL 到Python 函数的映射关系。

路由:处理 URL 和函数之间关系的程序。

  在 Flask 程序中,使用程序实例提供的 app.route 修饰器定义路由,把修饰的函数注册为路由。下面的例子说明了如何使用这个修饰器声明路由:

@app.route('/')
def index():
return '

Hello World!

'

视图函数和响应:前例把 index() 函数注册为程序根地址的处理程序。当浏览器访问了部署程序的服务器,会触发服务器执行 index() 函数。这个函数的返回值称为响应,是客户端接收到的内容。如果客户端是 Web 浏览器,响应就是显示给用户查看的文档。像 index() 这样的函数称为视图函数(view function)。视图函数返回的响应可以是包含HTML 的简单字符串,也可以是复杂的表单。

  某些 URL 格式会包含可变部分。尖括号中的内容就是动态部分,任何能匹配静态部分的 URL 都会映射到这个路由上。调用视图函数时,Flask 会将动态部分作为参数传入函数。
  路由中的动态部分默认使用字符串,不过也可使用类型定义。例如,路由 /user/ 只会匹配动态片段 id 为整数的 URL。Flask 支持在路由中使用 int、float 和 path 类型。代码如下所示:

path 类型:是字符串,但不把斜线视作分隔符,而将其当作动态片段的一部分。

@app.route('/user/')
def user(name):
	return '

Hello, %s!

'
% name

2.3 启动服务器

  程序实例用 run 方法启动 Flask 集成的开发 Web 服务器(flask提供的服务器不适合开发模式下使用):app.run( )函数可以接收设置web服务器操作模式的参数:调试模式 -> debug=True:

if __name__ == '__main__':
	app.run(debug=True)

name==’main'
  
用来判断程入口,在这里确保直接执行这个脚本时才启动开发Web 服务器。如果这个脚本由其他脚本引入,__name__显示的值为模块名。

2.4 一个完整的程序

程序代码如示例 2-1 所示。

from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
	return '

Hello World!

'
@app.route('/') def user('/user/<name>): return '

Hello, %s!

'
% name if __name__ == '__main__': app.run(debug=True)

2.5  请求-响应循环

现在你已经开发了一个简单的 Flask 程序,下面几节将介绍这个框架的一些设计理念。

2.5.1 程序和请求上下文

  Flask 从客户端收到请求时,要让视图函数能访问一些对象,这样才能处理请求。请求对象就是一个很好的例子,它封装了客户端发送的 HTTP 请求。Flask 使用上下文临时把某些对象变为全局可访问。有了上下文,就可以写出下面的视图函数:

from flask import request
@app.route('/')
def index():
	user_agent = request.headers.get('User-Agent')
	return '

Your browser is %s

'
% user_agent

注意:在这个视图函数中我们如何把 request 当作全局变量使用。事实上,request 不可能是全局变量。试想,在多线程服务器中,多个线程同时处理不同客户端发送的不同请求时,每个线程看到的 request 对象必然不同。Falsk 使用上下文让特定的变量在一个线程中全局可访问。

上下文:相当于一个容器,保存了 Flask 程序运行过程中的一些信息。

请求上下文变量,如下表所示:

变量 内容
request 封装了HTTP请求的内容,针对的是http请求。user = request.args.get(‘user’),获取的是get请求的参数。
session 用来记录请求会话中的信息,实现状态保持的设置,针对的是用户信息。session.get(‘name’)获取用户信息。

程序上下文变量,如下表所示:

变量 内容
g 处理请求时用作临时存储的对象。每次请求都会重设这个变量
current_app 当前激活程序的程序实例,用来记录程序运行过程中的配置信息,如记录项目的项目日志

注意:Flask 在分发请求之前激活(或推送)程序和请求上下文,请求处理完成后再将其删除。程序上下文被推送后,就可以在线程中使用 current_app 和 g 变量。request 和 session 变量。如果使用这些变量时我们没有激活程序上下文或请求上下文,就会导致错误。在程序实例上调用 app.app_context() 可获得一个程序上下文。

2.5.2 请求调度

  程序收到客户端发来的请求时,要找到处理该请求的视图函数。为了完成这个任务,Flask会在程序的 URL 映射中查找请求的 URL。Flask 使用 app.route 修饰器或者非修饰器形式的 app.add_url_rule() 生成映射。 要想查看 Flask 程序中的 URL 映射是什么样子,我们可以在 Python shell 中检查为 hello.py生成的映射。

URL 映射: URL 和视图函数之间的对应关系。

print(app.url_map)
---------------------------------------------------------
Map([<Rule '/' (HEAD, OPTIONS, GET) -> index>,
<Rule '/static/' (HEAD, OPTIONS, GET) -> static>,
<Rule '/user/' (HEAD, OPTIONS, GET) -> user>])

注意:URL 映射中的 HEAD、Options、GET 是请求方法,由路由进行处理。Flask 为每个路由都指定了请求方法,这样不同的请求方法发送到相同的 URL 上时,会使用不同的视图函数进行处理。HEAD 和 OPTIONS 方法由 Flask 自动处理,三个路由默认使用GET方法。可以在修饰器中添加请求方法:@app.route(’/’,[“GET”,“POST”])

2.5.3 请求钩子

  有时在处理请求之前或之后执行代码会很有用。例如,在请求开始时,我们可能需要创建数据库连接或者认证发起请求的用户。Flask 提供了注册通用函数的功能,注册的函数可在请求被分发到视图函数之前或之后调用。
请求钩子使用修饰器实现。Flask 支持以下 4 种钩子。

钩子 内容
before_first_request 注册一个函数,在处理第一个请求之前运行。
before_request 注册一个函数,在每次请求之前运行。
after_request 注册一个函数,如果没有未处理的异常抛出,在每次请求之后运行。
teardown_request 注册一个函数,即使有未处理的异常抛出,也在每次请求之后运行。

注意:在请求钩子函数和视图函数之间共享数据一般使用上下文全局变量 g。例如,before_request 处理程序可以从数据库中加载已登录用户,并将其保存到 g.user 中。随后调用视图函数时,视图函数再使用 g.user 获取用户。

2.5.4 响应

  Flask 调用视图函数后,会将其返回值作为响应的内容。大多数情况下,响应就是一个简单的字符串,作为 HTML 页面回送客户端。但 HTTP 协议需要的不仅是作为请求响应的字符串。HTTP 响应中一个很重要的部分是状态码。

(1)根据需求返回不同的状态码:如果视图函数返回的响应需要使用不同的状态码,那么可以把数字代码作为第二个返回值,添到响应文本之后。示例程序如下:

@app.route('/')
def index():
	return '

Bad Request

'
, 400

(2)Flask 视图函数还可以返回 Response 对象:make_response() 函数可接受 1 个、2 个或 3 个参数(和视图函数的返回值一样),并返回一个 Response 对象。有时我们需要在视图函数中进行这种转换,然后在响应对象上调用各种方法,进一步设置响应。下例创建了一个响应对象,然后设置了 cookie:

from flask import make_response
@app.route('/')
def index():
	response = make_response('

This document carries a cookie!

'
) response.set_cookie('answer', '42') return response

(3)将重定向的作为视图函数的返回类型。这种响应没有页面文档,只告诉浏览器一个新地址用以加载新页面。重定向经常在 Web 表单中使用。重定向经常使用 302 状态码表示,指向的地址由 Location 首部提供。Flask 提供了 redirect() 辅助函数,用于生成这种响应:

from flask import redirect
@app.route('/')
def index():
	return redirect('http://www.example.com')

由 abort 函数生成的响应,abort函数:flask中的异常处理语句。abort函数只能抛出符合http协议的异常状态码,在下面这个例子中,如果 URL 中动态参数 id 对应的用户不存在,就返回状态码 404:

作用:abort函数一般用来实现自定义的错误信息,让代码的扩展性更好,提高用户体验。

from flask import abort
@app.route('/user/')
def get_user(id):
	user = load_user(id)
	if not user:
		abort(404)
	return '

Hello, %s

'
% user.name

注意:abort 不会把控制权交还给调用它的函数,而是抛出异常把控制权交给 Web 服务器。只要触发abort后面的代码不会执行。

2.6 Flask扩展

  Flask 被设计为可扩展形式,故而没有提供一些重要的功能,例如数据库和用户认证,所以开发者可以自由选择最适合程序的包,或者按需求自行开发。接下来我们以在 hello.py 中添加一个扩展,使用命令行参数增强程序的功能为例。使用Flask-Script支持命令行选项,Flask 的开发 Web 服务器支持很多启动设置选项,但只能在脚本中作为参数传给app.run()函数。

Flask-Script :一个 Flask 扩展,为 Flask 程序添加了一个命令行解析器。Flask-Script 自带了一组常用选项,而且还支持自定义命令。Flask-Script 扩展使用 pip 安装:pip install flask-script

示例程序:

from flask import Flask
from flask_script import Manager

app = Flask(__name__)
manager = Manager(app)

@app.route('/')
def index():
	return '

Hello World!

'
if __name__ == '__main__': manager.run()

查看命令行的终端命令:python hello.py runserver --help
启动服务器的终端命令:python3 hello.py runserver -p 5000
代替app调用run方法:在python解释器的配置的script parameters中必须加入runserver
作用:可以在终端手动传入ip和port,可以自定义脚本参数,可以实现数据库的迁移

–host 参数是个很有用的选项,它告诉 Web 服务器在哪个网络接口上监听来自客户端的
连接。默认情况下,Flask 开发 Web 服务器监听 localhost 上的连接,所以只接受来自服
务器所在计算机发起的连接。

下述命令让 Web 服务器监听公共网络接口上的连接,允许同
网中的其他计算机连接服务器:
(1)python hello.py runserver --host 0.0.0.0
(2)Running on http://0.0.0.0:5000/
(3)Restarting with reloader
现在,Web 服务器可使用 http://a.b.c.d:5000/ 网络中的任一台电脑进行访问,其中“a.b.c.d”
是服务器所在计算机的外网 IP 地址。

你可能感兴趣的:(学习笔记)