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. Android P添加一个可以让system_server进程访问的hal service需要改动的sepolicy文件

    在device/sepolicy/common目录中: 修改文件attributes: attribute hal_newXX;attribute hal_newXX_client;attribute ...

  2. JSP元素介绍

    1.HTML注释 <!--这个HTML注释--> 2.JSP注释 <% --这是JSP注释-- %> 3.声明 用于在页面中定义变量或方法 <% ! String use ...

  3. 用 hugo 和 netlify 搭建blog【转】

    用 hugo 和 netlify 搭建blog - kok的笔记本 Releases · gohugoio/hugo · GitHub 测试baidu 测试163

  4. winform项目导入数据

    一.点击导入按钮,弹出文件选择框 这个方法的使用要引用下面两个命名空间: using System.Windows.Forms;using DevExpress.XtraEditors; privat ...

  5. thrift使用

    一.什么是thrift Thrift是一种接口描述语言和二进制通讯协议,它被用来定义和创建跨语言的服务.它被当作一个远程过程调用(RPC)框架来使用,是由FaceBook为“大规模跨语言服务开发”而开 ...

  6. Spring项目使用Junit4测试配置

    我们经常要写junit测试,在不启动整个web项目的情况下,测试自己的service实现或者是dao实现,我们来充分利用下junit4的强大功能. 1.junit4的测试类 import java.u ...

  7. com.fasterxml.jackson工具类

    老版本的Jackson使用的包名为org.codehaus.jackson,而新版本使用的是com.fasterxml.jackson. Jackson主要包含了3个模块: jackson-core ...

  8. Python高级笔记(四) -- 多继承_方法解析顺序表MRO

    1. 多继承以及MRO顺序 1.1 单独调用父类的方法 # -*- encoding=utf-8 -*- class Parent(object): def __init__(self, name): ...

  9. JGUI源码:右键菜单实现(12)

    1.要想实现右键菜单,就要先能响应右键函数 $('#down').mousedown(function(e){ if(3 == e.which){ alert('这是右键单击事件'); }else i ...

  10. mybatis中 keyProperty="id" 的作用

    keyProperty="id"的作用是: 一般都是结合数据库自动生成主键来使用,由于是数据库生成的主键, 所以在这个对象持久化到数据库之前是对象中的这个属性是没有属性值的,但是在 ...