4Flask的路由和cbv

Flask的路由

from  flask import Flask,url_for
app=Flask(__name__)
app.debug=True

# @app.route('/login',methods=['POST',"GET"],endpoint="sb")
#decorator
def login(nid):
    print(type(nid),nid)
    return "ojbk_login"
#rule --->就是路由
#enpoint,取别名,如果没有就用当前函数名
#enpoint,不能重复
#methods=["POST","GET"]
#view_func 就我们endpoint,指向的函数,也就请求该路由的时候,要响应函数
#app.add_url_rule(rule,‘取别名,反向解析’,login)
app.add_url_rule('/login/<string:nid>',view_func=login,endpoint="sb",methods=['POST',"GET"])

'''
取别名:
'''
# @app.route('/',endpoint="sb")
def index():
    real_url=url_for("sb")
    return real_url
app.add_url_rule('/index',view_func=index,methods=['POST',"GET"])




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)

        if methods is None:
            methods = getattr(view_func, 'methods', None) or ('GET',)
        if isinstance(methods, string_types):
            raise TypeError('Allowed methods have to be iterables of strings, '
                            'for example: @app.route(..., methods=["POST"])')
        methods = set(item.upper() for item in methods)

        required_methods = set(getattr(view_func, 'required_methods', ()))

        provide_automatic_options = getattr(view_func,
            'provide_automatic_options', None)

        if provide_automatic_options is None:
            if 'OPTIONS' not in methods:
                provide_automatic_options = True
                required_methods.add('OPTIONS')
            else:
                provide_automatic_options = False

        methods |= required_methods

        rule = self.url_rule_class(rule, methods=methods, **options)
        rule.provide_automatic_options = provide_automatic_options

        self.url_map.add(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

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

endpoint源码

    @setupmethod
    def endpoint(self, endpoint):
        def decorator(f):
            self.view_functions[endpoint] = f
            return f
        return decorator

app.add_url_rule 等同于 装饰器形式的 @app.route()

url_for 本质最后结果 通过别名来找到对应的 匹配url路径

Flask的cbv及路由注意点

from  flask import Flask,url_for,views
app=Flask(__name__)
app.debug=True
# class IndexView(views.View):
#     methods=["POST","GET"]
#     # decorators=[,,,,]
#     def dispatch_request(self):
#         print('Index')
#         return 'Index!'

class IndexView(views.MethodView):
    # methods=["GET"]
    # decorators=[,,,,]
    def get(self):
        print('Index')
        return 'Index!,get'
    def post(self):
        return 'Index!,post'

#IndexView.as_view(name='index')都views.View里面的as_view的view
#为什么要as_view(name='index'),
#如果不指定,就都是view
#所以必须指定

app.add_url_rule('/index', view_func= IndexView.as_view(name='index'))


#相当于我们的endpoint
# app.add_url_rule('/index', view_func=)

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

源码解读

    @classmethod
    def as_view(cls, name, *class_args, **class_kwargs):
        """Converts the class into an actual view function that can be used
        with the routing system.  Internally this generates a function on the
        fly which will instantiate the :class:`View` on each request and call
        the :meth:`dispatch_request` method on it.

        The arguments passed to :meth:`as_view` are forwarded to the
        constructor of the class.
        """
        def view(*args, **kwargs):
            self = view.view_class(*class_args, **class_kwargs)
            return self.dispatch_request(*args, **kwargs)

        if cls.decorators:
            view.__name__ = name
            view.__module__ = cls.__module__
            for decorator in cls.decorators:
                view = decorator(view)

        # We attach the view class to the view function for two reasons:
        # first of all it allows us to easily figure out what class-based
        # view this thing came from, secondly it's also used for instantiating
        # the view class so you can actually replace it with something else
        # for testing purposes and debugging.
        view.view_class = cls
        view.__name__ = name
        view.__doc__ = cls.__doc__
        view.__module__ = cls.__module__
        view.methods = cls.methods
        return view

ps: 这边的as_view的源码中的注释讲述了 最好使用不同的name来进行测试和调试, 否则会出现重名问题!!!

posted @ 2019-12-01 15:10  suren_apan  阅读(124)  评论(0编辑  收藏  举报