Warning: Can't synchronize with repository "(default)" (Unsupported version control system "svn": No module named svn). Look in the Trac log for more information.

Ticket #2458: REST_custom_get_actions.patch

File REST_custom_get_actions.patch, 3.5 KB (added by lento, 2 years ago)
  • tg/controllers/restcontroller.py

    Allow custom REST-like methods in a rest controller to dispatch to get_<custom>
    and post_<custom>
    
    diff -r 8153093fe448 tg/controllers/restcontroller.py
    a b  
    105105                state.add_method(method, new_remainder) 
    106106                return state 
    107107 
     108    def _handle_custom_get(self, state, remainder): 
     109        method_name = remainder[-1] 
     110        if method_name not in getattr(self, 'custom_actions', []): 
     111            return 
     112 
     113        current_controller = state.controller 
     114 
     115        if (self._is_exposed(current_controller, method_name) or 
     116           self._is_exposed(current_controller, 'get_%s' % method_name)): 
     117            method = self._find_first_exposed(current_controller, ('get_%s' % method_name, method_name)) 
     118            new_remainder = remainder[:-1] 
     119            if method and self._method_matches_args(method, state, new_remainder): 
     120                state.add_method(method, new_remainder) 
     121                return state 
     122 
     123    def _handle_custom_method(self, method, state, remainder): 
     124        current_controller = state.controller 
     125        method_name = method 
     126        method = self._find_first_exposed(current_controller, ('post_%s' % method_name, method_name)) 
     127 
     128        if method and self._method_matches_args(method, state, remainder): 
     129            state.add_method(method, remainder) 
     130            return state 
     131 
     132        #you may not send a delete request to a non-delete function 
     133        if remainder and self._is_exposed(current_controller, remainder[0]): 
     134            abort(405) 
     135 
     136        # there might be a sub-controller with a delete method, let's go see 
     137        if remainder: 
     138            sub_controller = getattr(current_controller, remainder[0], None) 
     139            if sub_controller: 
     140                remainder = remainder[1:] 
     141                state.current_controller = sub_controller 
     142                state.url_path = '/'.join(remainder) 
     143                r = self._dispatch_controller(state.url_path, sub_controller, state, remainder) 
     144                if r: 
     145                    return r 
     146        return self._dispatch_first_found_default_or_lookup(state, remainder) 
     147 
    108148    def _handle_get(self, method, state, remainder): 
    109149        current_controller = state.controller 
    110150        if not remainder: 
     
    119159                    return state 
    120160            return self._dispatch_first_found_default_or_lookup(state, remainder) 
    121161 
    122         #test for "edit" or "new" 
     162        #test for "delete", "edit" or "new" 
    123163        r = self._handle_delete_edit_or_new(state, remainder) 
    124164        if r: 
    125165            return r 
    126166 
     167        #test for custom REST-like attribute 
     168        r = self._handle_custom_get(state, remainder) 
     169        if r: 
     170            return r 
     171 
    127172        current_path = remainder[0] 
    128173        if self._is_exposed(current_controller, current_path): 
    129174            state.add_method(getattr(current_controller, current_path), remainder[1:]) 
     
    171216        if r: 
    172217            return r 
    173218 
    174         r = self._handler_lookup[state.http_method](self, state.http_method, state, remainder) 
     219        if state.http_method in self._handler_lookup.keys(): 
     220            r = self._handler_lookup[state.http_method](self, state.http_method, state, remainder) 
     221        else: 
     222            r = self._handle_custom_method(state.http_method, state, remainder) 
    175223 
    176224        #clear out the method hack 
    177225        if '_method' in pylons.request.POST: