Python Routes map.resource详解

来源:互联网 发布:电信4g网络接入点设置 编辑:程序博客网 时间:2024/06/05 04:51

文档参考:

http://routes.readthedocs.org/en/latest/introduction.html

demo参考:

http://blog.csdn.net/bellwhl/article/details/8956088

#!/usr/bin/env/python#coding=utf-8from routes import Mapperfrom routes import middlewareimport webob.decfrom wsgiref.simple_server import make_serverclass controller(object):    def __init__(self):        self.i = 1    def __call__(self):        print self.i    def search(self):        return "do search()"    def show(self):        return "do show()"    def index(self):        return "do index()"    def update(self):        return "do update()"    def delete(self):        return "do delete()"    def create(self):        return "do create()"    def create_many(self):        return "do create_many()"    def update_many(self):        return "do update_many()"    def list_many(self):        return "do list_many()"    def delete_many(self):        return "do delete_many()"    def preview(self):        return "do preview()"class appclass(object):    def __init__(self):        a = controller()        map = Mapper()        map.resource('message', 'messages', controller=a,                     path_prefix='/{projectid}', name_prefix='lala_',                     collection={'list_many': 'GET', 'create_many': 'POST'},                     member={'update_many': 'POST', 'delete_many': 'POST'},                     new={'preview' : 'POST'},                     parent_resource=dict(member_name="haha", collection_name="heihei"))        self.route = middleware.RoutesMiddleware(self.dispatch, map)    @webob.dec.wsgify    def __call__(self, req):        return self.route    @staticmethod    @webob.dec.wsgify    def dispatch(req):        match = req.environ['wsgiorg.routing_args'][1]        route = req.environ['routes.route']        print "route match result is:", match        if not match:            return "fake url"        print "route.name: %s, route.routepath: %s, route.conditions: %s" % (route.name, route.routepath, route.conditions)        controller = match['controller']        action = match['action']        if hasattr(controller, action):            func = getattr(controller, action)            ret = func()            return ret        else:            return "has no action:%s" % actionif __name__ == "__main__":    app = appclass()    server = make_server('', 8088, app)    server.serve_forever()


启动后,

1.  GET http://127.0.0.1:8088/project_id_value/messages

do index()

route match result is: {'action': u'index', 'projectid': u'project_id_value', 'controller': <__main__.controller object at 0x0000000002E570F0>}
route.name: lala_messages, route.routepath: /{projectid}/messages, route.conditions: {'method': ['GET']}

2. POST http://127.0.0.1:8088/project_id_value/messages

do create()

route match result is: {'action': u'create', 'projectid': u'project_id_value', 'controller': <__main__.controller object at 0x0000000002E570F0>}
route.name: None, route.routepath: /{projectid}/messages, route.conditions: {'method': ['POST']}

3. PUT http://127.0.0.1:8088/project_id_value/messages/1

do update()

route match result is: {'action': u'update', 'projectid': u'project_id_value', 'controller': <__main__.controller object at 0x0000000002E570F0>, 'id': u'1'}
route.name: None, route.routepath: /{projectid}/messages/:(id), route.conditions: {'method': ['PUT']}

4. DELETE http://127.0.0.1:8088/project_id_value/messages/1

do delete()

route match result is: {'action': u'delete', 'projectid': u'project_id_value', 'controller': <__main__.controller object at 0x0000000002E570F0>, 'id': u'1'}
route.name: None, route.routepath: /{projectid}/messages/:(id), route.conditions: {'method': ['DELETE']}

5. GET http://127.0.0.1:8088/project_id_value/messages/1

do show()

route match result is: {'action': u'show', 'projectid': u'project_id_value', 'controller': <__main__.controller object at 0x0000000002E570F0>, 'id': u'1'}
route.name: lala_message, route.routepath: /{projectid}/messages/:(id), route.conditions: {'method': ['GET']}

6. POST http://127.0.0.1:8088/project_id_value/messages/new/preview

do preview()

route match result is: {'action': u'preview', 'projectid': u'project_id_value', 'controller': <__main__.controller object at 0x0000000002E570F0>}
route.name: lala_preview_new_message, route.routepath: /{projectid}/messages/new/preview, route.conditions: {'method': ['POST']}

7. GET http://127.0.0.1:8088/project_id_value/messages/list_many

do list_many()

route match result is: {'action': u'list_many', 'projectid': u'project_id_value', 'controller': <__main__.controller object at 0x0000000002E570F0>}
route.name: lala_list_many_messages, route.routepath: /{projectid}/messages/list_many, route.conditions: {'method': ['GET']}

8. POST http://127.0.0.1:8088/project_id_value/messages/create_many

do create_many()

route match result is: {'action': u'create_many', 'projectid': u'project_id_value', 'controller': <__main__.controller object at 0x0000000002E570F0>}
route.name: lala_create_many_messages, route.routepath: /{projectid}/messages/create_many, route.conditions: {'method': ['POST']}

9. POST http://127.0.0.1:8088/project_id_value/messages/1/update_many

do update_many()

route match result is: {'action': u'update_many', 'projectid': u'project_id_value', 'controller': <__main__.controller object at 0x0000000002E570F0>, 'id': u'1'}
route.name: lala_update_many_message, route.routepath: /{projectid}/messages/:(id)/update_many, route.conditions: {'method': ['POST']}

10. POST http://127.0.0.1:8088/project_id_value/messages/1/delete_many

do delete_many()

route match result is: {'action': u'delete_many', 'projectid': u'project_id_value', 'controller': <__main__.controller object at 0x0000000002E570F0>, 'id': u'1'}
route.name: lala_delete_many_message, route.routepath: /{projectid}/messages/:(id)/delete_many, route.conditions: {'method': ['POST']}


注释掉path_prefix行,如下:

        map.resource('message', 'messages', controller=a,                     # path_prefix='/{projectid}', name_prefix='lala_',                     collection={'list_many': 'GET', 'create_many': 'POST'},                     member={'update_many': 'POST', 'delete_many': 'POST'},                     new={'preview' : 'POST'},                     parent_resource=dict(member_name="haha", collection_name="heihei"))

重启启动,注意route.name和route.routepath属性的变动:

1. GET http://127.0.0.1:8088/heihei/haha_value/messages

do index()

route match result is: {'action': u'index', 'controller': <__main__.controller object at 0x0000000002D7A0F0>, 'haha_id': u'haha_value'}
route.name: haha_messages, route.routepath: /heihei/:haha_id/messages, route.conditions: {'method': ['GET']}

2. POST http://127.0.0.1:8088/heihei/haha_value/messages/new/preview

do preview()

route match result is: {'action': u'preview', 'controller': <__main__.controller object at 0x0000000002D7A0F0>, 'haha_id': u'haha_value'}
route.name: haha_preview_new_message, route.routepath: /heihei/:haha_id/messages/new/preview, route.conditions: {'method': ['POST']}

3. GET http://127.0.0.1:8088/heihei/haha_value/messages/list_many

do list_many()

route match result is: {'action': u'list_many', 'controller': <__main__.controller object at 0x0000000002D7A0F0>, 'haha_id': u'haha_value'}
route.name: haha_list_many_messages, route.routepath: /heihei/:haha_id/messages/list_many, route.conditions: {'method': ['GET']}

...


map.resource源码:

<span style="font-size:12px;">def resource(self, member_name, collection_name, **kwargs):        collection = kwargs.pop('collection', {})        member = kwargs.pop('member', {})        new = kwargs.pop('new', {})        path_prefix = kwargs.pop('path_prefix', None)        name_prefix = kwargs.pop('name_prefix', None)        parent_resource = kwargs.pop('parent_resource', None)                # Generate ``path_prefix`` if ``path_prefix`` wasn't specified and         # ``parent_resource`` was. Likewise for ``name_prefix``. Make sure        # that ``path_prefix`` and ``name_prefix`` *always* take precedence if        # they are specified--in particular, we need to be careful when they        # are explicitly set to "".        if parent_resource is not None:             if path_prefix is None:                 path_prefix = '%s/:%s_id' % (parent_resource['collection_name'],                                              parent_resource['member_name'])             if name_prefix is None:                name_prefix = '%s_' % parent_resource['member_name']        else:            if path_prefix is None: path_prefix = ''            if name_prefix is None: name_prefix = ''                # Ensure the edit and new actions are in and GET        member['edit'] = 'GET'        new.update({'new': 'GET'})                # Make new dict's based off the old, except the old values become keys,        # and the old keys become items in a list as the value        def swap(dct, newdct):            """Swap the keys and values in the dict, and uppercase the values            from the dict during the swap."""            for key, val in dct.iteritems():                newdct.setdefault(val.upper(), []).append(key)            return newdct        collection_methods = swap(collection, {})        member_methods = swap(member, {})        new_methods = swap(new, {})                # Insert create, update, and destroy methods        collection_methods.setdefault('POST', []).insert(0, 'create')        member_methods.setdefault('PUT', []).insert(0, 'update')        member_methods.setdefault('DELETE', []).insert(0, 'delete')                # If there's a path prefix option, use it with the controller        controller = strip_slashes(collection_name)        path_prefix = strip_slashes(path_prefix)        path_prefix = '/' + path_prefix        if path_prefix and path_prefix != '/':            path = path_prefix + '/' + controller        else:            path = '/' + controller        collection_path = path        new_path = path + "/new"        member_path = path + "/:(id)"                options = {             'controller': kwargs.get('controller', controller),            '_member_name': member_name,            '_collection_name': collection_name,            '_parent_resource': parent_resource,            '_filter': kwargs.get('_filter')        }                def requirements_for(meth):            """Returns a new dict to be used for all route creation as the            route options"""            opts = options.copy()            if method != 'any':                 opts['conditions'] = {'method':[meth.upper()]}            return opts                # Add the routes for handling collection methods        for method, lst in collection_methods.iteritems():            primary = (method != 'GET' and lst.pop(0)) or None            route_options = requirements_for(method)            for action in lst:                route_options['action'] = action                route_name = "%s%s_%s" % (name_prefix, action, collection_name)                self.connect("formatted_" + route_name, "%s/%s.:(format)" % \                             (collection_path, action), **route_options)                self.connect(route_name, "%s/%s" % (collection_path, action),                                                    **route_options)            if primary:                route_options['action'] = primary                self.connect("%s.:(format)" % collection_path, **route_options)                self.connect(collection_path, **route_options)                # Specifically add in the built-in 'index' collection method and its         # formatted version        self.connect("formatted_" + name_prefix + collection_name,             collection_path + ".:(format)", action='index',             conditions={'method':['GET']}, **options)        self.connect(name_prefix + collection_name, collection_path,                      action='index', conditions={'method':['GET']}, **options)                # Add the routes that deal with new resource methods        for method, lst in new_methods.iteritems():            route_options = requirements_for(method)            for action in lst:                path = (action == 'new' and new_path) or "%s/%s" % (new_path,                                                                     action)                name = "new_" + member_name                if action != 'new':                    name = action + "_" + name                route_options['action'] = action                formatted_path = (action == 'new' and new_path + '.:(format)') or \                    "%s/%s.:(format)" % (new_path, action)                self.connect("formatted_" + name_prefix + name, formatted_path,                              **route_options)                self.connect(name_prefix + name, path, **route_options)        requirements_regexp = '[^\/]+(?<!\\\)'        # Add the routes that deal with member methods of a resource        for method, lst in member_methods.iteritems():            route_options = requirements_for(method)            route_options['requirements'] = {'id':requirements_regexp}            if method not in ['POST', 'GET', 'any']:                primary = lst.pop(0)            else:                primary = None            for action in lst:                route_options['action'] = action                self.connect("formatted_%s%s_%s" % (name_prefix, action,                                                     member_name),                    "%s/%s.:(format)" % (member_path, action), **route_options)                self.connect("%s%s_%s" % (name_prefix, action, member_name),                    "%s/%s" % (member_path, action), **route_options)            if primary:                route_options['action'] = primary                self.connect("%s.:(format)" % member_path, **route_options)                self.connect(member_path, **route_options)                # Specifically add the member 'show' method        route_options = requirements_for('GET')        route_options['action'] = 'show'        route_options['requirements'] = {'id':requirements_regexp}        self.connect("formatted_" + name_prefix + member_name,                      member_path + ".:(format)", **route_options)        self.connect(name_prefix + member_name, member_path, **route_options)</span>


解释参数:

controller
Use the specified controller rather than deducing it from the collection name.

collection
Additional URLs to allow for the collection. Example:

member
Additional URLs to allow for a member. Example:

new
Additional URLs to allow for new-member functionality.

path_prefix
Prepend the specified prefix to all URL patterns. The prefix may include path variables. This is mainly used to nest resources within resources.

name_prefix
Prefix the specified string to all route names. This is most often combined with path_prefix to nest resources:

parent_resource
A dict containing information about the parent resource, for creating a nested resource. It should contain the member_name and collection_name of the parent resource. This dict will be available via the associated Route object which can be accessed during a request via request.environ["routes.route"].
If parent_resource is supplied and path_prefix isn’t, path_prefix will be generated from parent_resource as “<parent collection name>/:<parent member name>_id”.
If parent_resource is supplied and name_prefix isn’t, name_prefix will be generated from parent_resource as “<parent member name>_”.



0 0