1 路由

 1.1app.url_map 查看所有路由

from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello_world():
"""定义视图函数"""
print(app.url_map)
return "hello flask" @app.route('/index')
def index():
return 'index' if __name__ == '__main__':
app.run(debug=True)

访问127.0.0.1 :5000

显示当前所有的路由,和每条路由的访问方式。

1.2通过method限定访问方式

给index函数添加method

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

此时去浏览器在地址栏输入地址访问,

很显然,不让get请求,给method列表中添加get请求方式。

@app.route('/index', methods=["post", 'get'])
def index():
return 'index'

此时就能get和post请求

1.3同一路由装饰多个视图函数

添加两个视图函数

@app.route('/test')
def test1():
return "test1" @app.route("/test")
def test2():
return "test2"

在浏览器访问127.0.0.1:5000/test,返回的是test1.

修改两个函数的请求方式

@app.route('/test', methods=["post"])
def test1():
return "test1" @app.route("/test", methods=["get"])
def test2():
return "test2"

再去浏览器访问127.0.0.1:5000/test,返回的是test2

1.4同一视图多个路由装饰器

添加一个func视图函数

@app.route("/func1")
@app.route("/func2")
def func():
return "func"

在浏览器访问127.0.0.1:5000/func1和 127.0.0.1:5000/func2,返回的结果都是func。

1.5 使用url_for进行反解析

添加一个login视图函数

from flask import Flask, redirect, url_for

@app.route("/login")
def login():
url = url_for("index") # 使用url_for,通过视图函数的名字找到视图对应url
return redirect(url)

访问127.0.0.1:5000/login,然后就会直接跳转到index页面。

1.6 动态路由

# 路由传递的参数默认当做string处理,这里指定int,尖括号中冒号后面的内容是动态的
@app.route('/book/<int:book_id>')
def book_detail(book_id):
return "book detail %s" % book_id

# 路由传递的参数默认当做string处理,这里指定int,尖括号中冒号后面的内容是动态的
# @app.route('/book/<int:book_id>')
@app.route('/book/<book_id>') # 不加转换器类型,默认时普通字符串规则,除了 / 字符
def book_detail(book_id):
return "book detail %s" % book_id

1.7 自定义转换器

from werkzeug.routing import BaseConverter

# 1.定义自己的转换器
class RegexConverter(BaseConverter): def __init__(self, url_map, regex):
# 调用父类的初始化方法
super().__init__(url_map)
# 将正则表达式的参数保存到对象的属性中, flask会去使用这个属性来进行路由的正则匹配
self.regex = regex # 2.将自定义的转换器添加到flask的应用中
app.url_map.converters["re"] = RegexConverter # 127.0.0.1:5000/send/178456123789
@app.route("/send/<re(r'1[34578]\d{9}'):mobile>")
def send_msg(mobile):
return "send_msg---To:%s" % mobile

1.8 转换器转换过程

自定义的转换器RegexConverter添加两个方法,他们都是父类BaseConverter的方法,现在看下他们其实是在做什么。

to_python

# 1.定义自己的转换器
class RegexConverter(BaseConverter): def __init__(self, url_map, regex):
# 调用父类的初始化方法
super().__init__(url_map)
# 将正则表达式的参数保存到对象的属性中, flask会去使用这个属性来进行路由的正则匹配
self.regex = regex def to_python(self, value):
print(value)
return 123 def to_url(self, value):
pass # 2.将自定义的转换器添加到flask的应用中
app.url_map.converters["re"] = RegexConverter # 127.0.0.1:5000/send/178456123789
@app.route("/send/<re(r'1[34578]\d{9}'):mobile>")
def send_msg(mobile):
return "send_msg---To:%s" % mobile

在浏览器访问http://127.0.0.1:5000/send/17845678912,页面显示

控制台属输出17845678912。转换过程:

to_url

class RegexConverter(BaseConverter):

    def __init__(self, url_map, regex):
# 调用父类的初始化方法
super().__init__(url_map)
# 将正则表达式的参数保存到对象的属性中, flask会去使用这个属性来进行路由的正则匹配
self.regex = regex def to_python(self, value):
# print(value)
# value是在路径进行正则表达式匹配的时候提取的参数
# return 123
return value def to_url(self, value):
print(value)
return "" # 2.将自定义的转换器添加到flask的应用中
app.url_map.converters["re"] = RegexConverter # 127.0.0.1:5000/send/178456123789
@app.route("/send/<re(r'1[34578]\d{9}'):mobile>")
def send_msg(mobile):
return "send_msg---To:%s" % mobile @app.route("/index")
def index():
url = url_for("send_msg", mobile="")
return redirect(url)

访问http://127.0.0.1:5000/index, 页面显示:

控制台输出:18732141231, 转换过程:

to_url是在使用url_for方法的时候被调用。

2 获取请求参数

from flask import request

就是 Flask 中表示当前请求的 request 对象,request对象中保存了一次HTTP请求的一切信息。

from flask import Flask, request

app = Flask(__name__)

@app.route("/index", methods=["get", 'post'])
def index():
# request中包含了前端发送过来的所有请求数据
# form和data是用来提取请求体数据
# 通过request.form可以直接提取请求体中的表单格式的数据, 是一个类字典的对象
# 通过get方法只能拿到多个同名参数的第一个
name = request.form.get("name")
age = request.form.get("age")
# getlist可以获取同名的所有数据
name_list = request.form.getlist("name")
print("request.data", request.data) # 发送json数据 # 127.0.0.1:5000/index?page=1 查询字符串 QueryString
# args使用提取url中的参数(查询字符串)
page = request.args.get("page")
print(page)
return "%s:%s,,%s" % (name, age, name_list) if __name__ == '__main__':
app.run()

2.1 上传文件 

已上传的文件存储在内存或是文件系统中一个临时的位置。你可以通过请求对象的 files 属性访问它们。每个上传的文件都会存储在这个字典里。它表现近乎为一个标准的 Python file 对象,但它还有一个 save() 方法,这个方法允许你把文件保存到服务器的文件系统上。这里是一个用它保存文件的例子:

@app.route("/upload", methods=['post'])
def upload():
# 接收前端发送过来的文件
file_obj = request.files.get("pic")
# if file_obj is None:
# return "未上传文件"
# # 将文件保存到本地
# # 1.创建一个文件对象
# f = open('./test.png', 'wb')
# # 2.向文件写内容
# content = file_obj.read()
# f.write(content)
# # 3.关闭文件
# f.close() # 直接使用上传文件的对象保存
file_obj.save("./test1.png")
return "上传成功"

3 abort函数与自定义异常处理

3.1 abort函数

from flask import abort
@app.route("/login", methods=['get'])
def login():
name = "hhh"
pwd = ''
if name != "aaa" or pwd != 123:
# 使用abort函数可以立即终止视图函数的执行, 并可以返回了浏览器特定的信息
# 1.传递状态码信息, 必须是标准的http状态码
abort(404)
# 2.传递响应体信息
# res = Response("login failed")
# abort(res)
return "login success"

3.2 自定义异常处理

@app.errorhandler(404)
def handle_error(err):
"""自定义处理错误方法"""
# 这个函数的返回值会是用户看到的最终结果
return "首页已换, 下次记得收藏网站。。%s" % err

4 返回的响应数据

 4.1 元组

可以返回一个元组,这样的元组必须是 (response, status, headers) 的形式,且至少包含一个元素。 status 值会覆盖状态代码, headers 可以是一个列表或字典,作为额外的消息标头值。

@app.route("/index")
def index():
# 使用元祖返回自定义的响应信息
# 响应头 状态码 响应头
# return "使用元祖返回自定义的响应信息", 400, [("name", "haha")]
# return "使用元祖返回自定义的响应信息", 400, {("name", "haha")}
# return "使用元祖返回自定义的响应信息", 666, {("name", "haha")}
# return "使用元祖返回自定义的响应信息", "666 mystatus", {("name", "haha")}
# return "使用元祖返回自定义的响应信息", "666 mystatus"

4.2 make_response

from flask import make_response

@app.route("/index")
def index():
# 使用make_response来构造响应信息
res = make_response("使用make_response来构造响应信息")
res.status = "666 mystatus" # 设置状态码
res.headers["name"] = "haha" # 设置响应头
return res

5 使用jsonify返回json数据

from flask import jsonify

@app.route("/index")
def index():
data = {"title": "santi", "price": 90}
# return json.dumps(data) # 此时响应头的Content-Type: text/html; charset=utf-8
# 手动设置Content-Type
# return json.dumps(data), 200, {"Content-Type": "application/json"}
# 使用jsonify, jsonify帮助转换json数据, 并设置响应头Content-Type": "application/json"
# return jsonify(data)
return jsonify(title="santi", price=90)

6 设置和读取cookie

from flask import Flask, make_response, request

app = Flask(__name__)

@app.route("/set_cookie")
def set_cookie():
res = make_response("set_cookie")
# 默认有效期是临时cookie, 浏览器关闭就失效
# res.set_cookie("name", "test")
# max_age设置有效期, 单位:秒
# res.set_cookie("name1", "test1", max_age=3600)
# 通过响应头设置cookie
# res.headers["Set-Cookie"] = "name2=test2; Expires=Sun, 28-Apr-2019 12:37:29 GMT; Max-Age=3600; Path=/"
return res @app.route("/get_cookie")
def get_cookie():
cook = request.cookies.get("name1")
return cook @app.route("/delete_cookie")
def delete_cookie():
res = make_response("delete_cookie")
res.delete_cookie("name1")
return res if __name__ == '__main__':
app.run()

7 session

from flask import session

需要设置secret_key
from flask import Flask, session

app = Flask(__name__)

app.config["SECRET_KEY"] = "qlxmxlnmj"

@app.route("/login")
def login():
# 设置session
session["name"] = "test"
return "login success" @app.route("/index")
def index():
# 获取session
name= session.get("name")
return "session :: %s" %name if __name__ == '__main__':
app.run()

8 请求上下文与应用上下文

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

Flask中有两种上下文,请求上下文和应用上下文。

8.1 请求上下文(request context)

request和session都属于请求上下文对象。

request:封装了HTTP请求的内容,针对的是http请求。举例:user = request.args.get('user'),获取的是get请求的参数。

session:用来记录请求会话中的信息,针对的是用户信息。举例:session['name'] = user.id,可以记录用户信息。还可以通过session.get('name')获取用户信息。

8.2 应用上下文(application context)

current_app和g都属于应用上下文对象。

current_app:表示当前运行程序文件的程序实例。我们可以通过current_app.name打印出当前应用程序实例的名字。

g:处理请求时,用于临时存储的对象,每次请求都会重设这个变量。比如:我们可以获取一些临时请求的用户信息。

  • 当调用app = Flask(_name_)的时候,创建了程序应用对象app;

  • request 在每次http请求发生时,WSGI server调用Flask.call();然后在Flask内部创建的request对象;

  • app的生命周期大于request和g,一个app存活期间,可能发生多次http请求,所以就会有多个request和g。

  • 最终传入视图函数,通过return、redirect或render_template生成response对象,返回给客户端。

区别: 请求上下文:保存了客户端和服务器交互的数据。 应用上下文:在flask程序运行过程中,保存的一些配置信息,比如程序文件名、数据库的连接、用户信息等。

9 请求钩子

在客户端和服务器交互的过程中,有些准备工作或扫尾工作需要处理,比如:在请求开始时,建立数据库连接;在请求结束时,指定数据的交互格式。为了让每个视图函数避免编写重复功能的代码,Flask提供了通用设施的功能,即请求钩子。

请求钩子是通过装饰器的形式实现,Flask支持如下四种请求钩子:

before_first_request:在处理第一个请求前运行。

before_request:在每次请求前运行。

after_request:如果没有未处理的异常抛出,在每次请求后运行。

teardown_request:在每次请求后运行,即使有未处理的异常抛出。

from flask import Flask

app = Flask(__name__)

@app.route("/index")
def index():
print("index 被执行")
return "index" @app.before_first_request
def handle_before_first_request():
"""在第一次请求处理之前被执行"""
print("handle_before_first_request 被执行") @app.before_request
def handle_before_request():
"""在每次请求之前都被执行"""
print("handle_before_request 被执行") @app.after_request
def handle_after_request(response):
"""在每次请求(视图函数处理)之后都被执行, 前提是视图函数没有出现异常"""
print("handle_after_request 被执行")
return response @app.teardown_request
def handle_teardown_request(response):
"""在每次请求(视图函数处理)之后都被执行, 无论视图函数是否出现异常,都被执行"""
print("handle_teardown_request 被执行")
return response if __name__ == '__main__':
app.run()

启动服务器,在浏览器访问index,控制台输出结果:

服务器不重启,再次刷新浏览器,控制台输出:

在index函数中添加一个异常,

from flask import Flask

app = Flask(__name__)

@app.route("/index")
def index():
print("index 被执行")
int("A")
return "index" @app.before_first_request
def handle_before_first_request():
"""在第一次请求处理之前被执行"""
print("handle_before_first_request 被执行") @app.before_request
def handle_before_request():
"""在每次请求之前都被执行"""
print("handle_before_request 被执行") @app.after_request
def handle_after_request(response):
"""在每次请求(视图函数处理)之后都被执行, 前提是视图函数没有出现异常"""
print("handle_after_request 被执行")
return response @app.teardown_request
def handle_teardown_request(response):
"""在每次请求(视图函数处理)之后都被执行, 无论视图函数是否出现异常,都被执行, 工作在非调试模式, debug=false"""
print("handle_teardown_request 被执行")
return response if __name__ == '__main__':
app.run()

把调试模式关了, 重启服务器,在浏览器访问,控制台输出:

10 Flask-Script扩展命令行

通过使用Flask-Script扩展,我们可以在Flask服务器启动的时候,通过命令行的方式传入参数。而不仅仅通过app.run()方法中传参,比如我们可以通过python hello.py runserver --host ip地址,告诉服务器在哪个网络接口监听来自客户端的连接。默认情况下,服务器只监听来自服务器所在计算机发起的连接,即localhost连接。

pip3 install Flask-Script
from flask import Flask
from flask_script import Manager app = Flask(__name__) # 创建Manager管理类的对象
manager = Manager(app) @app.route("/index")
def index():
return "index" if __name__ == '__main__':
# app.run()
# 通过管理对象来启动
manager.run()

Flask路由&视图的更多相关文章

  1. Flask路由+视图补充

    一.路由设置的两种方法 1.装饰器 @app.route('/index/') def index(): return 'Hello World!' 2.源码 route->decorator- ...

  2. flask路由和视图和cookie

    什么是路由 """ 客户端(例如web浏览器)把请求发送给Web服务器,Web服务器再把请求发送给Flask程序实例. 程序实例需要知道对每个URL请求运行那些代码,所以 ...

  3. 一、Flask路由介绍

    Flask介绍(轻量级的框架,非常快速的就能把程序搭建起来) Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是So ...

  4. Flask之视图(一)

    2.关于Flask 知识点 从Hello World开始 给路由传递参数 返回状态码 重定向 正则URL 设置cookie和获取cookie 扩展 上下文 请求钩子 Flask装饰器路由的实现 Fla ...

  5. Flask - 路由系统

    目录 Flask - 路由系统 @app.route()装饰器中的常用参数 methods : 当前 url 地址,允许访问的请求方式 endpoint:反向url地址,默认为视图函数名(url_fo ...

  6. Flask路由系统

    Flask路由系统 我们之前了解了路由系统是由带参数的装饰器完成的. 路由本质:装饰器和闭包实现的. 设置路由的两种方式 第一种: @app.route('/index') def index(): ...

  7. Flask ——路由系统

    Flask中的路由系统其实我们并不陌生了,从一开始到现在都一直在应用 @app.route("/",methods=["GET","POST" ...

  8. Laravel教程 二:路由,视图,控制器工作流程

    Laravel教程 二:路由,视图,控制器工作流程 此文章为原创文章,未经同意,禁止转载. View Controller 上一篇教程我们走了那么长的路,终于把Laravel安装好了,这一篇教程我们就 ...

  9. Vue-初步了解vue-router的三要素:路由map 、路由视图、路由导航

    安装vue-router模块 使用vue-router前要先安装vue-router库 cnpm install vue-router –save 使用vue-router vue-router有三个 ...

随机推荐

  1. CSS绝对定位元素居中的几种方法

    转载自-CSS居中绝对https://www.cnblogs.com/skura23/p/6530556.html 作者:PajamaCat 1,div宽度未知1 <body> <d ...

  2. UNION的使用方法 (表与表直接数据和在一起的示例)

    SELECT o.CATEGORY CATEGORY,o.KEY_WORK KEY_WORK FROM BO_EU_KEY_WORK wo RIGHT OUTER JOIN BO_EU_WORK_ON ...

  3. 【WebSocket】WebSocket介绍

    1.背景 在WebSocket出现之前客户端向服务器发出请求是通过http协议实现的,而http协议有个特点是通行请求只能由客户端发起,然后服务端响应查询结果,HTTP 协议没法让服务器主动向客户端推 ...

  4. MySQL架构备份

    MySQL Replication 概述 集群的主要类型? 高可用集群(High Available Cluster, HA) 高可用集群是指通过特殊的软件把独立的服务器连接起来,组成一个能够提供故障 ...

  5. 20165223《网络对抗技术》Exp4 恶意代码分析

    目录 -- 恶意代码分析 恶意代码分析说明 实验任务目标 实验内容概述 schtasks命令使用 实验内容 系统运行监控 恶意软件分析 静态分析 virscan分析和VirusTotal分析 PEiD ...

  6. 集合源码分析[2]-AbstractList 源码分析

    AbstractList 类型:抽象类 接口的继承以及实现关系 继承AbstractCollection 实现List接口 典型方法实现解析 public List<E> subList( ...

  7. CF271D 【Good Substrings】

    定义哈希函数 \(H(c)=\sum_{i = 1} ^ m c_i*b^{m-i}\) \(H(C,K+1)=H(C,K)*b+C_{K+1}\)(K个坏字母) 用long long #includ ...

  8. 【CF1157F】Maximum Balanced Circle

    题目大意:给定一个长度为 N 的序列,求是否能够从序列中选出一个集合,使得这个集合按照特定的顺序排成一个环后,环上相邻的点之间的权值差的绝对值不超过 1. 题解:集合问题与序列顺序无关,因此可以先将序 ...

  9. python正则表达式Re模块备忘录

    title: python正则表达式Re模块备忘录 date: 2019/1/31 18:17:08 toc: true --- python正则表达式Re模块备忘录 备忘录 python中的数量词为 ...

  10. OS + CentOS cmake

    s Linux编译安装cmake最新版本 https://blog.51cto.com/sadoc/1910753 https://cmake.org/download/ https://github ...