zoukankan      html  css  js  c++  java
  • Pecan控制器和路由系统

    Pecan路由采用的是对象分发机制,将HTTP请求分发到控制器,然后到控制器里定义的方法。

    对象分发机制将请求路径进行切割,根据请求路径从root控制器开始,按次序寻找路径对应的控制器及方法。

    一、控制器和路由实例

    from pecan import expose
    
    class BooksController(object):
        @expose()
        def index(self):
            return "Welcome to book section."
    
        @expose()
        def bestsellers(self):
            return "We have 5 books in the top 10."
    
    class CatalogController(object):
        @expose()
        def index(self):
            return "Welcome to the catalog."
    
        books = BooksController()
    
    class RootController(object):
        @expose()
        def index(self):
            return "Welcome to store.example.com!"
    
        @expose()
        def hours(self):
            return "Open 24/7 on the web."
    
        catalog = CatalogController()

    1, 访问/时,会由RootController类的index方法进行响应;

    2, 访问/hours或者/hours/时,会由RootController类的hours方法进行响应;

    3, 访问/catalog时,首先会通过RootController找到其catalog属性,也就是一个CatalogController实例,然后寻找CatalogController类的index方法进行响应;

    4, 访问/catalog/books时,首先会通过RootController找到其catalog属性,也就是一个CatalogController实例,然后寻找CatalogController类的books属性,也就是一个BookController实例,使用其index方法进行响应;

    5, 访问/catalog/books/bestsellers时,首先会通过RootController找到其catalog属性,也就是一个CatalogController实例,然后寻找CatalogController类的books属性,也就是一个BookController实例,使用其bestseller方法进行响应.

    二、expose 暴露控制器方法

    expose告诉Pecan类中的哪些方法是公开可见的 如果一个方法没有用修饰expose(),Pecan永远不会将请求路由到它。

    pecan默认采用expose进行路由绑定,需要路由控制器类的方法都要经过expose装饰器的装饰,pecan就可以使HTTP请求找到对应的方法。

    不同的使用方法会有不同的效果,如下:

    2.1 expose()

    from pecan import expose
     
    class RootController(object):
        @expose()
        def hello(self):
            return 'Hello World’

    被装饰的方法需要返回一个字符串,表示HTML响应的body。

    2.2 @expose(html_template_name)

    from pecan import expose
     
    class RootController(object):
        @expose('html_template.mako')
        def hello(self):
            return {'msg': 'Hello!’}
    <!-- html_template.mako -->
    <html>
        <body>${msg}</body>
    </html>

    被装饰的方法返回一个字典,字典的key可以在html模板中使用${key}的方式引用。

    2.3 @expose(route='some-path')

    例如有这样一个请求:/some-path,由于python语法限制,pecan并不能将该请求的处理方法声明为some-path。使用@expose(route='some-path'),被装饰方法将响应/some-path请求。

    class RootController(object):
     
        @expose(route='some-path')
        def some_path(self):
            return dict()

    注意:尽量不使用dict(),使用不当,HTTP状态码将是204,及服务器没有返回任何内容错误。

    另一种方式:pecan.route()

    class RootController(object):
     
        @expose()
        def some_path(self):
            return dict()
     
    pecan.route('some-path', RootController.some_path)

    延伸:利用route()方法来将请求路由给下一级控制器

    class ChildController(object):
     
        @expose()
        def child(self):
            return dict()
     
    class RootController(object):
        pass
     
    pecan.route(RootController, 'child-path', ChildController())

    在这个例子中,pecan应用将会给请求/child-path/child/返回HTTP 200响应。

    2.4 @expose(generic=True)

    expose()方法中的generic参数可以根据请求方法对URL进行重载,即一个url路径可以被两个不同的方法处理。

    class RootController(object):
    
        # HTTP GET /
        @expose(generic=True, template='json')
        def index(self):
            return dict()
    
        # HTTP POST /
        @index.when(method='POST', template='json')
        def index_POST(self, **kw):
            uuid = create_something()
            return dict(uuid=uuid)

    对于"/"的GET请求,由index()方法处理;对于"/"的POST请求,由index_POST方法处理。

    2.5 @expose()叠加用法

    class RootController(object):
        @expose('json')
        @expose('text_template.mako', content_type='text/plain')
        @expose('html_template.mako')
        def hello(self):
            return {'msg': 'Hello!'}

    叠加使用后一个hello方法可以响应三种格式的请求(application/json, text/plain, text/html)。

    当客户端请求/hello.json或者http header中包含“Accept: application/json”时,将hello()方法响应的名字空间渲染进json文本,及@expose('json')用法;

    当客户端请求/hello.txt或者http header中包含“Accept: text/plain”时,使用text_template.mako模板文件响应,即@expose('text_template.mako', content_type='text/plain')用法;

    当客户端请求/hello.html时,使用html_template.mako模板文件。如果客户端请求/hello,并且没有显式指明内容格式,则pecan默认使用text/html的内容格式进行响应,假设客户端想要HTML。

     2.6 _lookup()

    _lookup方法是最后尝试的方法,只有没有控制器可以响应请求的URL,而且最后找到的控制器没有定义_default方法时,采用_lookup。

    此方法返回一个新的控制器用于控制url的剩余部分,如下代码:

    def get_student_by_primary_key(num):
        a = ["xiao_ming", "xiao_li"]
        num = int(num) if type(num) == int and len(a) > int(num) else 0
        return a[num]
    
    
    class Addr(object):
        @expose()
        def index(self):
            return "addr"
    
    
    class StudentController(object):
        def __init__(self, student):
            self.student = student
    
        @expose()
        def name(self):
            return self.student
    
        addr = Addr()
    
    
    class RootController(object):
    
        @expose()
        def _lookup(self, primary_key, *remainder):
            student = get_student_by_primary_key(primary_key)
            if student:
                return StudentController(student), remainder
            else:
                return "404"

    例如"/1/name"路径,将走_lookup()方法,返回 StudentController(student), remainder;

    此时,StudentController(student) 是一个新的控制器,而remainder是url的剩余部分,即 name;

    StudentController() 控制器将找到def name(self) 进而响应请求。

    同理,对于"/100/addr",也走_lookup()方法,返回 StudentController(student), remainder;

    此时,StudentController(student) 是一个新的控制器,而remainder是url的剩余部分,即 addr;

    找到addr = Addr(),进而得到响应。

    2.7 _default()

     对于标准的对象路由分发机制,当没有任何控制器可以处理url是,_default将要作为最后一个方法被调度。

    from functools import wraps
    
    
    def happy_expose(f=None, **kw):
        if f is None:
            def inner_expose(func):
                return happy_expose(func, **kw)
            return inner_expose
        else:
            @wraps(f)
            @expose(**kw)
            def _expose(*args, **kwargs):
                return f(*args, **kwargs)
            return _expose
    class RootController(object):
    
        @expose()
        def hours(self):
            return "Open 24/7 on the web."
    
        @happy_expose
        def _default(self, *remainder):
            return 'Hello World from root default'

    _default方法是最后被调用的。

    结束!

  • 相关阅读:
    计算机相关单位换算关系的积累
    谈编程资料
    杂记toCSV
    [转载]Windows 8][Metro Style Apps]淺談Metro Style Apps的瀏覽模式及螢幕解析度
    [转载][Windows 8][Metro Style Apps]Windows 8 開發/執行環境概觀
    【转载】[Windows 8]Hello Windows 8 Windows 8 Developer Preview搶先預覽
    台湾dotnet程序员之家
    [转载]实现Application Tile 更新
    [转载]在.NET中实现OAuth身份认证
    杂记
  • 原文地址:https://www.cnblogs.com/aaronthon/p/14832494.html
Copyright © 2011-2022 走看看