Flask解析(二)路由(werkzeug.routing里 Map, Rule)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flask解析(二)路由(werkzeug.routing里 Map, Rule)相关的知识,希望对你有一定的参考价值。

参考技术A

这章是跟着上一章讲的,如有不适应请点击 上一章
服务器里的路由是一个非常重要的角色,它控制了路径与视图函数的关联。
url的是统一资源定位符,对可以从 互联网 上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址。互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。
常见的url是:122.227.20.190:8000/index
可以分成:

通俗的讲

Werkzeug 库的routing模块的主要功能在于URL解析。对于WSGI应用来讲,不同的URL对应不同的视图函数,routing模块则会对请求信息的URL进行解析并匹配,触发URL对应的视图函数,以此生成一个响应信息。routing模块的解析和匹配功能主要体现在三个类上:Rule、Map和MapAdapter。

Rule类继承自RuleFactory类。一个Rule的实例代表一个URL模式,一个WSGI应用可以处理很多不同的URL模式,这也就是说可以产生很多不同的Rule实例。这些Rule实例最终会作为参数传递给Map类,形成一个包含所有URL模式的对象,通过这个对象可以解析并匹配请求对应的视图函数。

关于Rule类有一些常用的方法:

rule实例化时至少接受一个参数,其他的都是默认参数。这个类实现了match,build等方法。主要的方法有get_url方法,这个方法重写了父类RuleFactory的方法,返回的是自身的生成器。这个方法与submain等其他的类的实现方法不同,在submain类中,这个类本身包含了rule类,故调用get_urls方法首先获得rule实例,再一次调用get_url得到一个生成器。
另外一个方法是bind方法,这个方法将rule实例绑定到map实例上,绑定后的rule能够使用map属性的方法。

通过Map类构造的实例可以存储所有的URL规则,这些规则是Rule类的实例。Map实例可以 通过后续的调用和给定的URL进行匹配。

关于Map类有一些常用的方法:

map类相当于一个存放Rule类的容器,实现的方法能对rule进行操作,也是url进入特定视图函数的中介。

MapAdapter主要是获取请求的url参数,将参数传递至相关视图函数中,进行处理。

Flask

Flask有两大核心:Werkzeug和Jinja2

Werkzeug实现路由,调试和web服务器网关接口,Werkzeug库的routing模块负责URL的解析,不同的URL对应不同的视图函数.

routing模块内部有:

Rule类: 用来构造不同的URL模式的对象,路由URL规则

Map类: 存储所有的URL规则和一些配置参数

BaseConverter的子类,负责匹配的规则

MapAdapter类: 负责协调Rule做具体的匹配工作

Jinja2实现模板.

 

 

 

from flask import Flask

app = Flask(__name__)

@app.route("/")

def hello():

  return "hello world"

if __name__ == "__main__":

  app.run()

Flask模块介绍:

from flask import Flask

# __name__:会认为该文件所在的目录就是flask项目目录

# static_url_path:访问静态文件的前缀

# static_folder: 静态文件所在的目录文件夹名称

# template_folder:模板文件所在的目录文件夹名称

app = Flask(__name__,

      static_url_path="/static",

      static_folder ="static",

      template_folder ="templates")

@app.route("/")

def index():

  return "index"

if __name__ == "__main__":

  app.run()

 

加载项目配置信息

from flask import Flask

# 自定义项目配置类

class Config(object):

  DEBUG = True

app =Flask(__name__)

# 方式一:使用类的方式加载配置信息(重点)

app.config.from_object(Config)

# 方式二:在同级目录中建立一个配置文件(‘my.ini‘)

app.config.from_pyfile(‘my.ini‘)

# 方式三:使用环境变量方式加载项目配置信息

# 跟方式二一样,先写一哥配置文件,然后将文件的路径加入到环境变量中

技术分享图片

# config的本质是一个字典

@app.route("/")

def hello():

  # 两种方式获取字典的值,

  # get方式获取不到则不会报错,默认为空

  print(app.config.get("DEBUG",""))

  # 找不到会报错

  print(app.config["DEBUG"]")

  return "hello world"

if __name__ == "__main__":

  # 0.0.0.0表示本机所有ip均可访问, port代表端口号

  app.run(host="0.0.0.0", port = 8888, debug=True)

 转换器提取url路径的参数

from flask import Flask

app = Flask(__name__)

@app.route("/")

def demo1():

  return "hello world"

# <user_id>转换器提取url路径的参数

# user_id的类型默认是字符串类型

# 127.0.0.1/user/字符串类型的数据

@app("/user/<user_id>")

def demo3(user_id):

  return "user_id:%s" % user_id

# 限制输入的数据类型

# 127.0.0.1:5000/user_id/int数据类型

@app.route("/user_id/<int:user_id>")

def demo4(user_id):

  return "user_id"% user_id

 

if __name__=="__main__"

  app.run(debug=True)

 

请求方式:GET及POST

from flask import Flask

app = Flask(__name__)

# 不设置默认是get请求方式

@app.route("/")

def hello_world():

  return "hello world"

# 设置post请求方式

@app.route("/post", methods=["POST"])

def demo():

  return "post success"

if __name__ == "__main__":

  print(app.url_map)

  app.run(debug=True)

 

 

自定义转换器类

 from flask import Flask

from werkzeug.routing import BaseConverter

 

app = Flask(__name__)

# 自定义转换器

class RegexConverter(BaseConverter):

  # 重写regex属性,当你将正则表达式传入给它,BaseConverter类帮你处理

  # url_map,re只是参数

  def  __init__(self, url_map, re):

    # 初始化父类

    super(RegexConverter, self).__init__(url_map)

    self.regex = re

# 注册正则匹配类

# 往flask源码里面添加一个键值对

"""

往flask源码里面添加一个键值对

{

re:RegexConverter

}

"""

# 将re转换成RegexConverter类

app.url_map.converters["re"] = RegexConverter

# re("d{6}")-->RegexConverter(app.url_map, "d{6}")

@app.route("/user/<re("d{6}"):user_id>)

def demo1(user_id):

  return "user %s" % user_id

 

if __name__ == "__main__":

  app.run(debug=True)

 

获取请求参数:

data: 记录请求的数据

form: post请求中的表单数据

args: get请求中的参数

cookies: 记录请求中的cookie信息

headers: 记录请求中的报文头

method: 记录请求使用的http请求方法

url: 记录请求的URL地址

files:记录请求上传的文件

 

from flask import Flask, request

# 默认请求时get请求,127.0.0.1:5000/get?user_name=kangkang&age=18

@app.route("/get")

def demo1():

"""提取get请求号后面携带的参数"""

#request.method属性获取访问方式,后面的请求方式必须大写

  if request.method == "GET":

    user_name = request.args.get("user_name", "")

    age = request.args.get("age")

    return "%s %s" %(user_name, age)

  else:

    return "请求方式错误405!"

# post请求提取参数

# 需要指明请求方式为POST

@app.route("/post", methods = [‘POST‘])

def demo2():

  if request.method == "POST":

    user_name = request.form.get("user_name", "")

    age = request.form.get("age", "")

    return "%s %s"%(user_name, user_id)

  else:

    return "405请求方式错误"

# 文件上传

@app.route("/upload", methods=["POST"])

def demo3():

  if request.method == "POST":

    file = request.files.get("pic", "")

    # 将图片保存到服务器本地

    file.save("./1.png")

  else:

    return "405请求方式错误"

 

if __name__ == "__main__":

  app.run(debug=True)

注意点:

GET:获取服务器的数据,问号里面携带的参数,告知服务器我要什么类型的数据

POST:往服务器新增数据,请求体里面携带参数,一般是需要存入的数据

 

 

构造响应数据:

import json

from flask import Flask, jsonify

app = Flask(__name__)

 

@app.route("/")

def demo1():

# json数据转换

dict = {

  "name":"kangkang",

  "age":24,

  "info":{

    "team":"laker"

    }

  }

# 序列化,将python对象转化成json字符串

json_str = json.dumps(dict)

# 反序列化:将json字符串转换成python对象

my_dict = json.loads(json_str)

# jsonify:能够将python对象转换成json对象

# 能够将响应体数据封装成响应对象并返回

# 指明了响应数据的格式:ContentType = "application/json"

my_json = jsonify(dict)

return my_json

 

if __name__ == "__main__":

   app.run(debug=True)

 

重定向

from flask import Flask, redirect, url_for

# redirect:重定向,输入指定的路径会跳转到指定的地址

# url_for("要重定向的函数名称","参数值")

app = Flask(__name__)

@app.route("/index/<int:user_id>")

def hello(user_id):

  return "hello %d" user_id

@app.route("/demo2")

def demo2():

  # 重定向到百度

  return redirect("www.baidu.com)

@app.route("/demo3")

def demo3():

# 重定向到指定的函数

# url_for:反向解析函数

# 传入的函数名称--->解析对应的url,根据app.app_url就能返回对应的url

  return redirect(url_for(‘hello‘, user_id = 6666))

 

if __name__ == "__main__":

  app.run(debug=True)

 

 

 

 

    

以上是关于Flask解析(二)路由(werkzeug.routing里 Map, Rule)的主要内容,如果未能解决你的问题,请参考以下文章

源码解析flask的路由系统

Flask之基于route装饰器的路由系统(源码阅读解析)

flask 关于 url_for的解析方式

Flask之路由注册

Flask 学习之 路由

Flask 蓝图(Blueprint)使用方式解析