【python】Flask之路由

一、关于路由

所谓路由,就是处理请求URL和函数之间关系的程序

根据例子看源码

from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
    return 'hello world!'

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

Flask中对URL规则进行统一管理的,创建URL规则有两种方式:

  1. 使用@app.route修饰器
    传入URL规则作为参数,将函数绑定到URL,这个过程便将一个函数注册为路由,这个函数则被称为视图函数
  2. 使用app.add_url_rule()

二、注册路由

定位到@app.route修饰器,看看route是什么

def route(self, rule, **options):
    def decorator(f):
        endpoint = options.pop("endpoint", None)
        self.add_url_rule(rule, endpoint, f, **options)
        return f
    return decorator

很明显,这是一个装饰器,route()有两个参数,rule表示url规则
该函数对参数进行处理之后,调用方法add_url_role(),这里也就验证了两种注册路由的方法等价

继续定位add_url_rule这个方法:

@setupmethod
    def add_url_rule(
        self,
        rule,
        endpoint=None,
        view_func=None,
        provide_automatic_options=None,
        **options
    ):
   ....

这个方法传入的参数有这些:

  • rule: url规则
  • endpoint: 要注册规则的endpoint,默认是视图函数的名
  • view_func: 视图函数
  • provide_automatic_options: 请求方法是否添加OPTIONS方法的一个标志
  • options: 关于请求处理的一些方法等

三、endpoint

着重介绍下endpoint,中文意思是端点
flask内部先把URL地址映射到端点(endpoint)上,然后再映射到视图函数(view_func)
看一个例子:

from flask import Flask

app = Flask(__name__)

@app.route('/', endpoint="say_hello")
def index():
    return 'hello world!'

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

继续看源码add_url_rule:

...

        if endpoint is None:
            endpoint = _endpoint_from_view_func(view_func)
        options["endpoint"] = endpoint
        methods = options.pop("methods", None)

这句话的意思是说如果endpoint没有, 就调用_endpoint_from_view_func方法,看一下_endpoint_from_view_func方法知道它其实就是返回view_func的名称

def _endpoint_from_view_func(view_func):
    """Internal helper that returns the default endpoint for a given
    function.  This always is the function name.

"""
    assert view_func is not None, "expected view func if endpoint is not provided."
    return view_func.__name__

所以通常来说,endpoint 不写,默认值就是和view_func同一个名称

作用

那么它的作用是什么呢?
端点通常用作反向查询URL地址(viewfunction–>endpoint–>URL)

例如,在flask中有个视图,想把它关联到另一个视图上(或从站点的一处连接到另一处), 可以直接使用URL_for()
看一个例子:

from flask import Flask, url_for, redirect

app = Flask(__name__)

@app.route('/')
def index():

    login_url = url_for('login', name="tony")
    print(login_url)
    return redirect(login_url)
    return '这是首页'

@app.route('/login/')
def login(name):
    print("name=", name)
    return '这是登录页面'

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

四、url_for()与重定向

url(路由)和函数视图的映射关系,即通过对应的url可以返回对应的视图函数。当然通过视图函数也能找到对应的url路径,这可以通过url_for来完成

4.1 url_for

在浏览网页的时候都会有跳转,假设写跳转时用url路径,当整个网站路径需要修改时需要更改这些代码,如果使用的是url_for修改量就很少(通常视图函数是不修改)
看看url_for的使用:

@app.route('/post/list//')
def my_list(page):
    return 'my list'

print(url_for('my_list',page=1,count=2))

4.2 重定向

重定向分为永久性重定向和暂时性重定向,在页面上体现的操作就是浏览器会从一个页面自动跳转到另外一个页面。比如用户访问了一个需要权限的页面,但是该用户当前并没有登录,因此应重定向到登录页面
具体操作如下:

from flask import Flask,request,redirect,url_for

app = Flask(__name__)

@app.route('/login/')
def login():
    return '这是登录页面'

@app.route('/profile/')
def profile():
    if request.args.get('name'):
        return '个人中心页面'
    else:

        return redirect(url_for('login'))

五、路由匹配

在应用初始化的过程中,会注册所有的路由规则,可以调用 app.url_map查看,当服务收到URL请求时,就需要进行路由匹配,以找到对应的视图函数,对应的流程和原理是什么呢?

当用户请求进入Flask应用时,首先会调用Flask里面的__call__方法,这个方法会调用Flask类的wsgi_app方法:

class Flask(_PackageBoundObject):
....

    def __call__(self, environ, start_response):
        """The WSGI server calls the Flask application object as the
        WSGI application. This calls :meth:wsgi_app which can be
        wrapped to applying middleware."""
        return self.wsgi_app(environ, start_response)

定位wsgi_app方法:

def wsgi_app(self, environ, start_response):
        ctx = self.request_context(environ)
        error = None
        try:
            try:
                ctx.push()
                response = self.full_dispatch_request()
            except Exception as e:
                error = e
                response = self.handle_exception(e)
            except:
                error = sys.exc_info()[1]
                raise
            return response(environ, start_response)
        finally:
            if self.should_ignore_error(error):
                error = None
            ctx.auto_pop(error)

该函数的处理过程包括:

  1. 创建RequestContext对象,在对象初始化的过程中调用app.create_url_adapter()方法,将请求参数environ传给Map对象创建MapAdapter对象,保存在url_adapter字段中
  2. 将RequestContext对象推入_request_ctx_stack栈中
  3. 通过RequestContext的match_request方法,调用MapAdapter对象的match方法找到匹配的Rule并解析出参数,保存在request的url_rule和view_args字段中
  4. 调用full_dispatch_request()

接下来看下full_dispatch_request方法:

def full_dispatch_request(self):
        self.try_trigger_before_first_request_functions()
        try:
            request_started.send(self)
            rv = self.preprocess_request()
            if rv is None:
                rv = self.dispatch_request()
        except Exception as e:
            rv = self.handle_user_exception(e)
        return self.finalize_request(rv)

看到这里调用了self.dispatch_request()方法:

def dispatch_request(self):

        req = _request_ctx_stack.top.request
        if req.routing_exception is not None:
            self.raise_routing_exception(req)
        rule = req.url_rule

        if (
            getattr(rule, "provide_automatic_options", False)
            and req.method == "OPTIONS"
        ):
            return self.make_default_options_response()

        return self.view_functions[rule.endpoint](**req.view_args)

处理的过程是:

  1. 获取请求对象的request,找到对应的endpoint
  2. 从view_functions中找到对应的视图函数,传递请求参数
  3. 视图函数处理内部逻辑并返回,完成一次请求分发

六、动态路由

6.1 动态路由传参

http://127.0.0.1:5000/student_list/2/

在path中有可变的部分,达到了传参的目的,称之为动态路由传参

@app.route('/student_list//')
def student_list(student_id):
    return '学生{}号的信息'.format(student_id)

6.2 动态路由的过滤

可以对参数限定数据类型,比如限定为student_id必须为整数类型

http://127.0.0.1:5000/student_list/2/
@app.route('/student_list//')
def article_detail(student_id):
    print(student_id, type(student_id))
    return '学生{}号的信息'.format(student_id)

主要有这几种类型过滤:

  • string: 默认的数据类型,接收没有任何斜杠” /”的字符串
  • int: 整型
  • float: 浮点型
  • path: 和string类型相似,但是接受斜杠,如:可以接受参数/aa/bb/cc/多条放在一起
  • uuid: 只接受uuid格式的字符串字符串

提示:uuid为全宇宙唯一的串

七、视图函数的URL路由设置

7.1 app.url_map查看所有路由

Flask的路由可以通过视图函数的修饰器@app.route()来配置访问url
在Django中可以在urls.py中查看所有视图的url信息,那么Flask如何查看所有视图url的信息呢?

【python】Flask之路由
可以看到日志中打印出了url的信息

; 7.2 使用methods设置视图请求的方式

在Flask的视图配置了url之后,默认是只支持GET请求的。如果需要处理POST请求,则需要使用methods参数设置一下


@app.route('/post_only', methods=["POST"])
def post_only():
    return "post only page"

在浏览器访问: http://127.0.0.1:5000/post_only

【python】Flask之路由
可以看到不允许GET请求

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

在同一个url路由的请求下,可以会有GET\POST\DELETE\PUT等多个不同的业务处理
那么就需要使用不同的视图函数来区分处理

@app.route('/hello', methods=["GET"])
def hello_get():
    return "hello_get"

@app.route('/hello', methods=["POST"])
def hello_post():
    return "hello_post"
  • 测试访问GET请求 http://127.0.0.1:5000/hello
    【python】Flask之路由
  • 测试访问POST请求 http://127.0.0.1:5000/hello
    【python】Flask之路由
    从结果来看,同一个url下,根据配置不同的method,则可以设置到不同的视图函数进行业务处理

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

一个视图如何定义多个url进行访问?
在Django中只要在urls.py中设置多行url定义即可,而在Flask中只需要使用多个路由修饰器进行定义


@app.route('/diff_url1')
@app.route('/diff_url2')
def diff_url():
    return "diff url"
  • 访问第一个url地址 http://127.0.0.1:5000/diff_url1
    【python】Flask之路由
  • 访问第二个url地址 http://127.0.0.1:5000/diff_url2
    【python】Flask之路由

7.5 使用 url_for 进行反解析

在Flask中则可以使用url_for来进行反向解析,而Flask的视图函数不需要设置name,而是直接使用视图函数的函数名即可

from flask import  redirect, url_for

@app.route('/hello', methods=["GET"])
def hello_get():
    return "hello_get"

@app.route('/url_for_test')
def url_for_test():
    return redirect(url_for('hello_get'))

测试访问 http://127.0.0.1:5000/url_for_test

【python】Flask之路由
可以看到页面自动跳转至hello_get的视图函数中

Original: https://blog.csdn.net/lluozh2015/article/details/123119604
Author: sysu_lluozh
Title: 【python】Flask之路由

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/732868/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • python zip 函数

    Python 2023年5月24日
    070
  • kubernetes集群最新版安装

    虚拟机准备 我这里准备了三台虚拟机,分别部署一个master和两个node,操作系统位ubuntu 20.04。 以下为特殊说明为三台机器都要做此操作 安装容器runtime 之前…

    Python 2023年10月21日
    061
  • 关于scrapy的代理问题

    今天帮同学解决scrapy的时候发现的,就是在我这里能运行,在他那里不能运行。对比scrapy的版本发现,他的是最新的(2.6.3),然后我的是2.5.0的。随后我将他的版本也换成…

    Python 2023年10月31日
    045
  • Docker部署Flask网站

    最近练练手,防止忘了,在docker上部署了下Flask网站。先单步进行,后面可以通过docker compose直接部署。 docker运行mysql,数据持久化到宿主机本地硬盘…

    Python 2023年8月10日
    059
  • python—scrapy数据解析、存储

    数据解析 当前文件 :D:\python_test\scrapyProject\scrapyProject\spiders\first.py import scrapy class…

    Python 2023年10月2日
    041
  • [附源码]Node.js计算机毕业设计高校社团管理系统Express

    项目运行 环境配置: Node.js 最新版+ V s code + Mysql5.7 + HBuilderX+Navicat11+Vue。 项目技术: Express 框架+ N…

    Python 2023年10月7日
    038
  • 难怪家里的网总不好!原来是路由器的天线摆错了!

    你是否有这样的困扰,家里的千兆WiFi,用的也是上好的WiFi6路由器,但网络总是不好,看视频不流畅,打游戏延迟高,总是找不到原因。 其实我们都忽略了一点,就是路由器的天线,天线是…

    Python 2023年10月29日
    039
  • salesforce零基础学习(一百一十八)Restrict Rule

    本篇参考: https://help.salesforce.com/s/articleView?id=sf.security_restriction_rule.htm&ty…

    Python 2023年10月21日
    051
  • pytest文档9-参数化parametrize

    前言 pytest.mark.parametrize装饰器可以实现测试用例参数化。 parametrizing 1.这里是一个实现检查一定的输入和期望输出测试功能的典型例子 con…

    Python 2023年9月15日
    042
  • 分享一个连接远端计算机与传输文件的脚本

    分享一个脚本,它将ssh和scp命令整合,可以连接特定的远端计算机,或者收发文件。免去记忆繁琐的命令,使用起来非常方便 分享一个连接远端计算机与传输文件的脚本 用了一个月超算,由于…

    Python 2023年10月14日
    043
  • python50行小游戏_50行python代码实现的贪吃蛇小游戏

    50行python代码实现的贪吃蛇小游戏 发布于 2014-09-01 21:26:24 | 1337 次阅读 | 评论: 1 | 来源: 网友投递 Python编程语言Pytho…

    Python 2023年9月20日
    053
  • pytest_allure_jenkins_email

    搭建一个接口自动化测试框架可以使用以下工具和技术: 1. Python:作为主要开发语言,可以使用 Python_来编写测试脚本和测试用例。 2. _Pytest:一款功能强大的 …

    Python 2023年9月14日
    052
  • if语句

    第4节.if语句 4.1 if语句的简单示例 cars=[‘audi’,’bmw’,’subaru’,’toyota’]for car in cars:    if car==’b…

    Python 2023年6月3日
    080
  • 手把手教你win10下安装Anaconda

    1.简介: Anaconda简单理解来说,就是一个大的环境池子,池子里面有不同的环境。每个环境用不同的名称进行标识。当我们需要哪个环境时,就在anaconda中激活哪个环境去使用即…

    Python 2023年8月2日
    042
  • 知识表示学习(三):TransR

    一.摘要 知识图谱补全旨在执行实体之间的链接预测。 在本文中,我们考虑了知识图嵌入的方法。 最近,诸如 TransE 和 TransH 等模型通过将关系视为从头实体到尾实体的翻译来…

    Python 2023年10月9日
    052
  • LRU缓存及实现

    一、淘汰策略 缓存:缓存作为一种平衡高速设备与低速设备读写速度之间差异而引入的中间层,利用的是局部性原理。比如一条数据在刚被访问过只有就很可能再次被访问到,因此将其暂存到内存中的缓…

    Python 2023年6月16日
    087
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球