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. asp.net core开源项目

    Orchard框架:https://www.xcode.me/code/asp-net-core-cms-orchard https://orchardproject.net/ https://git ...

  2. CountDownLatch类实现同步

    首先我们看一个普通的多线程代码 class MyThread implements Runnable { @Override public void run() { System.out.printl ...

  3. Windows安装MongoDB 4.0并赋予用户访问权限

    第一部分 Windows安装MongoDB-4.0 第一步:下载MongoDB:https://www.mongodb.com/download-center?jmp=nav#community 我目 ...

  4. poj-1904(强连通缩点)

    题意:有n个王子,每个王子都有k个喜欢的女生,王子挑选喜欢的女生匹配,然后再给你n个王子最开始就定好的匹配,每个王子输出能够结合且不影响其他王子的女生匹配 解题思路:强连通缩点,每个王子与其喜欢的女生 ...

  5. Nmap小技巧——探测大网络空间中的存活主机

    Nmap快速探测空间主机是否存活的技巧(来自lijiejie师傅): nmap -v -sn -PE -n --min-hostgroup --min-parallelism -oX nmap_out ...

  6. python中的技巧——杂记

    杂记 zip的用法 对于 a = [1,2,3] b = [3,2,1] 若要同时遍历 for x, y in zip(a, b): pass zip(a, b)=> [(1,2,3),(3,2 ...

  7. Luogu3768简单的数学题

    题目描述 题解 我们在一通化简上面的式子之后得到了这么个东西. 前面的可以除法分块做,后面的∑T2∑dµ(T/d)是积性函数,可以线性筛. 然后这个数据范围好像不太支持线性筛,所以考虑杜教筛. 后面那 ...

  8. kubernetes学习第一篇-k8s安装以及HelloWorld

    安装 1. 关闭防火墙服务 # systemctl disable firewalld # systemctl stop firewalld 2. 安装etcd以及kubernetes软件 yum i ...

  9. JWT 加密

    什么是JWT Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点 ...

  10. 自定义element-ui中的图标

    element-ui图标库图标较少,比如有关于登录页面输入框里的用户名和密码的小图标就没有,这个时候可以自定义图标. <el-input v-model="loginForm.user ...