flask(2.0)

一. Flask基础(一)

1.Flask启动

from flask import Flask
app = Flask(__name__)
@app.route("/index"):
def index():
    return "Hello"
app.run(host="0.0.0.0", port=9527, debug=True)

2.路由

methods = ["GET", "POST", "PUT", "DELETE"]

# 示例:
@app.route("/index", methods=["POAT", "GET"])

3.Response

# 5个返回类型:

# 三剑客
1. 直接返回字符串 HttpResponse
2. 返回模板字符串 render_template
3. 重定向 redirect

# 两个特殊值
4. 打开并返回文件内容 send_file("文件的路径")
5. 标准JSON格式的Response jsonify({"name":"Tom"})
	Content-type:application/json

4.Request

from flask import request
1. method	# 获取当前请求的 请求方式
2. url		# 获取完整访问路径,包含url参数
3. path		# 获取路由地址
4. form		# 获取FormData中的数据
	- to_dict()
    - get()
5. args		# 获取url中的参数数据
	- to_dict()
    - get()
6. values	# 深坑,通常用于查看args和FormData中的数据
7. json		# 请求头中Content-type:application/json数据会存放在request.json中
8. data		# 请求头中Content-type不被认可时,会将原始的请求体中的数据存放成Bytes类型的数据,Content-type:application/json也会保存原始请求体信息

5.Jinja2

{{}}	# 变量,函数
{%%}	# 逻辑代码

6.session

from flask import session	# 导入session
app.secret_key = "~!@#$%^"	# 设置反序列化秘钥
session["user"] = "value"	# 添加一个session值

Flask会将序列化后的session字符串存放在客户端的cookies中.

二.Flask基础(二)

1.路由配置

@app.route()装饰器中的参数:
    methods
    endpoint
    defaults
    strict_slashes
    redirect_to
    subdomain

(1)methods

描述: 允许进入当前视图函数的请求方式.

@app.route("/index", methods=["GET", "POST"])
def index():
    return "index"

注意: 不写methods参数时默认是只允许GET请求, 写methods参数时要指定所有允许的请求方式, 默认方式会被methods覆盖.

(2)endpoint

描述: 反向url地址,默认为视图函数名, url_for利用它进行反向解析.

from flask import Flask, url_for

@app.route("/info", methods=["GET", "POST"], endpoint='s_info')
def stu_info():
    print(url_for('s_info')) # 利用s_info反向解析本视图函数的路由地址 /info
    return "student info"

注意: endpoint默认与视图函数名一致, 不写endpoint参数则使用视图函数名反向解析, 即url_for('stu_info'), 有endpoint参数则使用该参数进行反向解析.

(3)defaults

描述: 视图函数的参数默认值.

@app.route("/info", methods=["GET", "POST"], defaults={"nid": 100})
def stu_info(nid):
    print(nid)   # 100
    return "student info"

注意: 视图函数一定要接收这个参数, 且形参名称一定要与defaults参数中的key保持一致.

(4)strict_slashes

描述: 是否严格遵守URL地址规则, 若strict_slashes=True, 那么在url地址末尾不可以出现斜杆/, 反之则可以.

(5)redirect_to

描述: 永久重定向

# 访问地址: /info 浏览器跳转至 /infos

@app.route("/info", redirect_to="/infos")
def student_info():
    return "Hello info"

@app.route("/infos")
def student_infos():
    return "Hello infos"

注意: 在跳转之前进行重定向, 原url对应的视图函数没有执行, 立即跳转到新的url, 且使用一次后浏览器会有缓存.

(6)subdomain

描述: 子域名前缀 subdomian="car" 这样写可以得到 car.oldboy.com 前提是app.config["SERVER_NAME"] = "oldboy.com"

app.config["SERVER_NAME"] = "oldboy.com"

@app.route("/info",subdomain="car")
def student_info():
    return "Hello info"

# 访问地址为:  car.oldboy.com/inf

2.动态路由参数

实例1

from flask import Flask, url_for

app = Flask(__name__)

@app.route("/info/<int:nid>", methods=["GET", "POST"], endpoint="s_info")
def student_info(nid):
    print(nid, type(nid))   # 1 <class 'int'>
    print(url_for("s_info", nid=nid))  # /info/1
    print(url_for("s_info", nid=2))    # /info/2
    return "Hello info"

app.run()

# 访问地址: http://127.0.0.1:5000/info/1  可以
# 访问地址: http://127.0.0.1:5000/info/e  报错

实例2

from flask import Flask, url_for

app = Flask(__name__)

@app.route("/info/<string:nid>", methods=["GET", "POST"], endpoint="s_info")
def student_info(nid):
    print(nid, type(nid))   # 1 <class 'str'>
    return "Hello info"

app.run()

# 访问地址:  http://127.0.0.1:5000/info/1   可以   
# 访问地址:  http://127.0.0.1:5000/info/e   可以

实例3

from flask import Flask, url_for

app = Flask(__name__)

@app.route("/info/<nid>", methods=["GET", "POST"], endpoint="s_info")
def student_info(nid):
    print(nid, type(nid))   # 1 <class 'str'>
    return "Hello info"

app.run()

# 访问地址:  http://127.0.0.1:5000/info/1    可以
# 访问地址:  http://127.0.0.1:5000/info/e    可以 

总结

通过以上示例发现, <int:nid>就是在url后定义一个参数接收url中的参数, 当定义int类型时只能传数字, 当定义string类型时可以接收数字和字符串, 当不定义类型时, 默认是string类型.

注意: 这种动态参数路由, 在url_for的时候, 一定要将动态参数名+参数值添加进去, 否则会抛出参数错误的异常.

3.Flask实例化配置

app = Flask(__name__, )

实例化对象时的参数如下:

# 常用:
template_folder="templates"		# 默认模板存放目录 templates
static_folder="static"			# 默认静态文件存放目录 static
static_url_path="/static"		# 访问静态文件路由地址,默认是"/"+static_folder

# 不常用:
static_host=None		# 指定静态文件服务器地址
host_matching=False		# 若不是特别需要时,慎用,否则所有的route 都需要host=""的参数
instance_path=None		# 指向另一个Flask实例的路径
root_path=None			# 主模块所在的目录的绝对路径,默认项目目录

4.Flask对象配置

Flask对象即Flask的实例化对象app, Flask的对象配置就是在 app.config 中添加键值对, 例如, app.config["SECRET_KEY"]="/wrwfgs", 但是你存进去的键必须是config中应该存在的, 如果不存在的话, 它没有任何用处, 所以我们来看一下config中有哪些key以及对应的作用.

  'DEBUG': False,  # 是否开启Debug模式
  'TESTING': False,  # 是否开启测试模式
  'SECRET_KEY': None # 在启用Flask内置Session的时候/开启flash,一定要有它
  'PERMANENT_SESSION_LIFETIME': 31,  # days , Session的生命周期(天)默认31天
  'SESSION_COOKIE_NAME': 'session',  # 在cookies中存放session加密字符串的名字

  'PROPAGATE_EXCEPTIONS': None,  # 异常传播(是否在控制台打印LOG) 当Debug或者testing开启后,自动为True
  'PRESERVE_CONTEXT_ON_EXCEPTION': None,  # 一两句话说不清楚,一般不用它
  'SECRET_KEY': None,  # 之前遇到过,在启用Session的时候,一定要有它
  'PERMANENT_SESSION_LIFETIME': 31,  # days , Session的生命周期(天)默认31天
  'USE_X_SENDFILE': False,  # 是否弃用 x_sendfile
  'LOGGER_NAME': None,  # 日志记录器的名称
  'LOGGER_HANDLER_POLICY': 'always',
  'SERVER_NAME': None,  # 服务访问域名
  'APPLICATION_ROOT': None,  # 项目的完整路径
  'SESSION_COOKIE_NAME': 'session',  # 在cookies中存放session加密字符串的名字
  'SESSION_COOKIE_DOMAIN': None,  # 在哪个域名下会产生session记录在cookies中
  'SESSION_COOKIE_PATH': None,  # cookies的路径
  'SESSION_COOKIE_HTTPONLY': True,  # 控制 cookie 是否应被设置 httponly 的标志,
  'SESSION_COOKIE_SECURE': False,  # 控制 cookie 是否应被设置安全标志
  'SESSION_REFRESH_EACH_REQUEST': True,  # 这个标志控制永久会话如何刷新
  'MAX_CONTENT_LENGTH': None,  # 如果设置为字节数, Flask 会拒绝内容长度大于此值的请求进入,并返回一个 413 状态码
  'SEND_FILE_MAX_AGE_DEFAULT': 12,  # hours 默认缓存控制的最大期限
  'TRAP_BAD_REQUEST_ERRORS': False,
  # 如果这个值被设置为 True ,Flask不会执行 HTTP 异常的错误处理,而是像对待其它异常一样,
  # 通过异常栈让它冒泡地抛出。这对于需要找出 HTTP 异常源头的可怕调试情形是有用的。
  'TRAP_HTTP_EXCEPTIONS': False,
  # Werkzeug 处理请求中的特定数据的内部数据结构会抛出同样也是“错误的请求”异常的特殊的 key errors 。
  # 同样地,为了保持一致,许多操作可以显式地抛出 BadRequest 异常。
  # 因为在调试中,你希望准确地找出异常的原因,这个设置用于在这些情形下调试。
  'EXPLAIN_TEMPLATE_LOADING': False,  # 如果这个值被设置为True,你只会得到常规的回溯。
  'PREFERRED_URL_SCHEME': 'http',  # 生成URL的时候如果没有可用的 URL 模式话将使用这个值
  'JSON_AS_ASCII': True,
  # 默认情况下 Flask 使用 ascii 编码来序列化对象。如果这个值被设置为 False ,
  # Flask不会将其编码为 ASCII,并且按原样输出,返回它的 unicode 字符串。
  # 比如 jsonfiy 会自动地采用 utf-8 来编码它然后才进行传输。
  'JSON_SORT_KEYS': True,
  # 默认情况下 Flask 按照 JSON 对象的键的顺序来序来序列化它。
  # 这样做是为了确保键的顺序不会受到字典的哈希种子的影响,从而返回的值每次都是一致的,不会造成无用的额外 HTTP 缓存。
  # 你可以通过修改这个配置的值来覆盖默认的操作。但这是不被推荐的做法因为这个默认的行为可能会给你在性能的代价上带来改善。
  'JSONIFY_PRETTYPRINT_REGULAR': True,
  'JSONIFY_MIMETYPE': 'application/json',
  'TEMPLATES_AUTO_RELOAD': None,
"""
查看所有配置项:
app.default_config
"""

以上这些key都可以被改写, 当然它们也有默认值, 如果没有特殊情况, 不要改写它的默认值.

除了单独修改某一项的配置外, 还可以通过类的方式导入配置:

# 新建settings.py文件

class MyConfig(object):
    DEBUG = True
    SECRET_KEY = "~!@#$%^"
    SESSION_COOKIE_NAME = "flask_session"
# 在flask启动文件中加载配置项

from flask import Flask
app = Flask(__name__)

from settings import MyConfig		# 导入配置文件
app.config.from_object(MyConfig)	# 加载配置文件

5.特殊装饰器

描述: 类似于Django的中间件.

from flask import Flask

app = Flask(__name__)

@app.before_request
def be1():
	print('我是be1')

@app.before_request
def be2():
	print('我是be2')

@app.before_request
def be3():
	print('我是be3')

@app.after_request
def af1(response):
	print('我是af1')
	return response

@app.after_request
def af2(response):
	print('我是af2')
	return response

@app.after_request
def af3(response):
	print('我是af3')
	return response

@app.route('/index')
def index():
	print('我是视图函数')
	return 'ok'

if __name__ == '__main__':
	app.run(debug=True)
# 总结:
before_request	# 在请求进入视图函数之前作出响应
after_request	# 在视图函数处理之后,响应返回客户端之前

# 代码书写顺序:
    be1 -> be2 -> be3 -> view -> af1 -> af2 -> af3
# 代码执行顺序:
	正常情况: 返回顺序是书写代码时的倒序
    be1 -> be2 -> be3 -> view -> af3 -> af2 -> af1
    异常情况: 异常阻塞请求的情况,不经过视图函数
    be1 -> af3 -> af2 -> af1

6.重定义错误提示errorhandler

from falsk import Flask, render_template

app = Flask(__name__)

@app.errorhandler(404)	# 参数是错误码
def error404(error_msg):	# 必须接收错误信息
    print(error_msg)
    return render_template("error404.html")

if __name__ == "__main__":
    app.run()

7.before_first_request

@app.before_first_request	# 当前客户端第一次访问此应用(不会被阻塞)
def bfe():
    print("当前客户端第一次访问此应用")
    return "ok"

8.Flask蓝图(Blueprint)

实例一

初学flask, 可以将蓝图理解为没有run方法的Flask对象.

# 新建flask_project/app01/views.py

from flask import Blueprint		# 导入蓝图

bp1 = Blueprint("bp1", __name__)	# 实例化蓝图对象

@bp1.route("/stulist")
def stulist():
    return "student list"
# 新建flask_project/manage.py

from flask import Flask
from app01 import views

app = Flask(__name__)

app.register_blueprint(views.bp1)	# 注册蓝图

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

运行manage.py文件启动flask项目, 浏览器访问http://127.0.0.1:5000/stulist即可看到返回结果.

蓝图可以指定url前缀(url_prefix参数), 有如下两种方法:

  • 方法一: 实例化蓝图对象时指定url前缀

    • bp1 = Blueprint("bp1", __name__, url_prefix="app01")
      
  • 方法二: 在注册蓝图时指定url前缀

    • app.register_blueprint(views.bp1, url_prefix="app01")
      

此时, 浏览器访问http://127.0.0.1:5000/app01/stulist可看到返回结果.

实例二

# app01/views/user.py

from flask import Blueprint

user_bp = Blueprint("user", __name__, url_prefix="/app01")


@user_bp.route("/user")
def user():
    return "I am user Blueprint"
# app01/__init__.py

from flask import Flask
from app01.views.user import user_bp


def create_app01():
    app01 = Flask(__name__)
    app01.register_blueprint(user_bp)
    return app01
# manager.py

from app01 import create_app01

my_app01 = create_app01()

if __name__ == '__main__':
    my_app01.run(host="0.0.0.0", port=5000, debug=True)

三.蓝图实例演练

基于蓝图实现一个内存增删改查, 数据如下:

STUDENT_DICT = {
	1: {'name': 'Old', 'age': 38, 'gender': '中'},
	2: {'name': 'Boy', 'age': 73, 'gender': '男'},
	3: {'name': 'EDU', 'age': 84, 'gender': '女'},
}

待续...

posted @ 2019-03-03 17:43  咕噜噜~  阅读(1156)  评论(0编辑  收藏  举报