码迷,mamicode.com
首页 > 其他好文 > 详细

Flask路由层

时间:2019-11-12 19:50:17      阅读:60      评论:0      收藏:0      [点我收藏+]

标签:cli   world   tle   pat   网上   互联网   资源   关系   gpo   

一:URL简介

1:定义

url是统一资源定位符(Uniform Resource Locator的简写),对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址。互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。

2:组成

scheme://host:port/path/?parameter=xxx#anchor
https://www.baidu.com/Public/linux/?fr=aladdin#23
  • scheme:代表的是访问的协议,一般为http或者https以及ftp等。
  • host:主机名,域名,比如www.baidu.com。
  • port:端口号。当你访问一个网站的时候,浏览器默认使用80端口。
  • path:路径。比如:www.baidu.com/Public/linux/?python=aladdin#23,www.baidu.com后面的Public/linux就是path。
  • query-string:查询字符串,比如:www.baidu.com/s?wd=python,?后面的python=aladdin就是查询字符串。
  • anchor:锚点,后台一般不用管,前端用来做页面定位的。比如:https://www.oldboyedu.com/Public/linux/?fr=aladdin#23 ,#后面的23就是锚点

3:作用

顾名思义统一资源定位符,是用来做定位用的,我们的web开发无非是要调用程序,而调用的具体程序我们称之为python的视图函数,URL建立了与Python视图函数一一对应的映射关系,通俗易懂可以理解为一条命令触发了一个python的函数或类。

二:URL使用方式

1:简介

在Flask程序中使用路由我们称之为注册路由,是使用程序实例提供的app.route()装饰器注册路由,而括号内的字符串就是url,注册路由的过程就是完成了 url和python类或函数映射的过程,可以理解为会有一张表保存了url与python类或函数的对应关系。这样我们以url访问flask就可以找到对应的程序

@app.route(/)
def hello_world():
    return Hello World!

技术图片

 2:url传参方式

2.1:动态传参

例如,你想根据学生的id找到具体的学生,http://127.0.0.1:5000/student_list/<student_id>/ 仍然在path部分 ,但是你没必要写多个路由,我们Flask支持这种可变的路由。

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

技术图片

 2.2:动态路由过滤

可以对参数限定数据类型,比如上面的文章详情,限定student_id必须为整数类型

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

技术图片

主要有这几种类型过滤:

  string: 默认的数据类型,接收没有任何斜杠"  /"的字符串

  int: 整型

  float: 浮点型

  path: 和string类型相似,但是接受斜杠,如:可以接受参数/aa/bb/cc/多条放在一起

  uuid: 只接受uuid格式的字符串字符串,

3: url_for()的使用:

3.1简介视图函数:

我们在访问一个网址的时候在调用flask项目的时候需要调用的是一段具体的代码,也就是一个python类或者python函数,在这里这个python类我们称之为视图类,python函数我们称之为视图函数。

3.2 url_for()的作用:

如果我们在视图函数中想使用一个url,比如给前端返回,或者我们在这个视图函数中返回一个模板文件都会使用到url,url相当于一把钥匙可以开启一些资源。如果你修改了注册路由编写的url规则,相当于修改了钥匙。那么其他的视图函数依旧是使用了原来的钥匙就无效了,如果项目是一个大项目,你一点点手动的去改涉及到的的url就不合理了。url_for()就是用来解决这个问题的。

3.3url_for()的原理:

利用视图函数名字一般不会改变的特性,利用视图函数的名字去动态精准的获取url,以便于开发使用。

url_for(视图函数名字)   # 输出该视图函数url
技术图片
from flask import Flask,url_for

app = Flask(__name__)
app.config.update(DEBUG=True)
@app.route(/,endpoint="sb")
def index():
    real_url=url_for("sb")
    return real_url

if __name__ == __main__:
    app.run()
技术图片

 四:路由源码分析

技术图片
from flask import Flask

app = Flask(__name__)

@app.route(/)
def hello_world():
    return Hello World!


if __name__ == __main__:
    app.run()
技术图片

1:第一步

技术图片

 2:第二步

技术图片

 3:第三步

技术图片

 4:第四步

技术图片

 PS:

(1)此处装饰器参数f 即为上述被装饰的函数

(2)灵魂代码为:self.add_url_rule(rule, endpoint, f, **options)

self.add_url_rule(rule, endpoint, f, **options)
‘‘‘
self 当前flask产生的对象 app
endpoint:函数别名
f:当前被装饰的函数
‘‘‘

5:第五步

技术图片

 PS;

1:首先判断是否有别名 如果没有别名走该_endpoint_from_view_func方法

2:如果有别名使用自己的传入的别名

技术图片

3:判断是否传入请求方式 如果没有传入请求方式 默认使用get方式

技术图片

 4:别名不能重复

技术图片

 4.1:

1:首先假设没有传入别名 即old_func为空 条件不成立

2:条件不成立 别名为当前函数名 此时别名不为空了

3:再次调用的时候 别名会有值 如果不和函数名相同 直接异常

4:如果别名相同 那么当调用函数的时候 有多个函数别名相同 该调用哪个函数

 六:CBV

1:基本使用方式

技术图片
from flask import Flask,  views

app = Flask(__name__)
app.debug = True


class IndexView(views.View):


    def dispatch_request(self):
        print(Index)
        return Index!

app.add_url_rule(‘/index‘, view_func= IndexView.as_view(name=‘index‘))
技术图片

2:问题探讨

(1)为什么as_view()括号内加上name

(2)为什么执行dispatch_request 而不是像django GET,POST等

3:源码分析

(1)走父类的as_view方法

技术图片
@classmethod
def as_view(cls, name, *class_args, **class_kwargs):
    ‘‘‘
    
    :param cls: 
    :param name: 从代码中可以看到 name这个参数必须传递
    :param class_args: 
    :param class_kwargs: 
    :return: 
    
    部分代码展示
    ‘‘‘

    def view(*args, **kwargs):
        self = view.view_class(*class_args, **class_kwargs)
        return self.dispatch_request(*args, **kwargs)
    
    # view 上述view函数

    view.view_class = cls  # view_class 绑定当前类
    view.__name__ = name  # 将函数名称 更改为传过来的名称
 
    return view   # 返回当前函数
技术图片

PS:

1:假设上述不传递name这个参数 上述路由可以更改为

app.add_url_rule(/index, view_func=view)

2:从上述更改的路由可以看到 所有的路由都指向一个view函数

3:代码分析add_url_rule

技术图片
        if view_func is not None:
            old_func = self.view_functions.get(endpoint)
            if old_func is not None and old_func != view_func:
                raise AssertionError(
                    "View function mapping is overwriting an "
                    "existing endpoint function: %s" % endpoint
                )
            self.view_functions[endpoint] = view_func  # 根路由
技术图片

PS:

(1)如果不传递name 

(2)首先获取不到别名 别名默认为函数名

(3)当再次访问的时候 如果函数名不等于别名 则会直接抛出异常

  def view(*args, **kwargs):
            self = view.view_class(*class_args, **class_kwargs)
            return self.dispatch_request(*args, **kwargs)

1:上述self 为当前类名称

2:在类中可以调用dispatch_request方法

七:CBV改良模式

1:改良

技术图片
class IndexView(views.MethodView):
    methods=["GET","POST"]

    def get(self):
        print(Index)
        return Index!,get
    def post(self):
        return Index!,post
技术图片

2:源码分析

技术图片
    def dispatch_request(self, *args, **kwargs):
        meth = getattr(self, request.method.lower(), None)
        if meth is None and request.method == "HEAD":
            meth = getattr(self, "get", None)

        assert meth is not None, "Unimplemented method %r" % request.method
        return meth(*args, **kwargs)
技术图片

 1

Flask路由层

标签:cli   world   tle   pat   网上   互联网   资源   关系   gpo   

原文地址:https://www.cnblogs.com/asdaa/p/11844546.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!