Added support for mapping parameters in the URI to parameters for a
controller, including validation support.
This commit is contained in:
@@ -71,7 +71,7 @@ class Pecan(object):
|
||||
def route(self, node, path):
|
||||
path = path.split('/')[1:]
|
||||
node, remainder = lookup_controller(node, path)
|
||||
return node
|
||||
return node, remainder
|
||||
|
||||
def handle_security(self, controller):
|
||||
if controller.pecan.get('secured', False):
|
||||
@@ -90,11 +90,20 @@ class Pecan(object):
|
||||
for hook in state.hooks:
|
||||
getattr(hook, hook_type)(*args)
|
||||
|
||||
def get_params(self, all_params, argspec):
|
||||
def get_params(self, all_params, remainder, argspec):
|
||||
valid_params = dict()
|
||||
|
||||
# handle params that are POST or GET variables first
|
||||
for param_name, param_value in all_params.iteritems():
|
||||
if param_name in argspec.args:
|
||||
valid_params[param_name] = param_value
|
||||
|
||||
# handle positional arguments
|
||||
for i, value in enumerate(remainder):
|
||||
if len(argspec.args) > (i+1):
|
||||
if valid_params.get(argspec.args[i+1]) is None:
|
||||
valid_params[argspec.args[i+1]] = value
|
||||
|
||||
return valid_params
|
||||
|
||||
def validate(self, schema, params=None, json=False):
|
||||
@@ -111,7 +120,7 @@ class Pecan(object):
|
||||
if '.' in path.split('/')[-1]:
|
||||
path, format = path.split('.')
|
||||
content_type = self.get_content_type(format)
|
||||
controller = self.route(self.root, path)
|
||||
controller, remainder = self.route(self.root, path)
|
||||
|
||||
# determine content type
|
||||
if content_type is None:
|
||||
@@ -129,6 +138,7 @@ class Pecan(object):
|
||||
# fetch and validate any parameters
|
||||
params = self.get_params(
|
||||
dict(state.request.str_params),
|
||||
remainder,
|
||||
controller.pecan['argspec']
|
||||
)
|
||||
if 'schema' in controller.pecan:
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
from pecan import Pecan, expose, request, response, redirect
|
||||
from webtest import TestApp
|
||||
from formencode import Schema, validators
|
||||
|
||||
|
||||
class TestBase(object):
|
||||
|
||||
@@ -192,4 +194,46 @@ class TestEngines(object):
|
||||
assert r.status_int == 302
|
||||
r = r.follow()
|
||||
assert r.status_int == 200
|
||||
assert r.body == 'it worked!'
|
||||
assert r.body == 'it worked!'
|
||||
|
||||
def test_uri_to_parameter_mapping(self):
|
||||
class RootController(object):
|
||||
@expose()
|
||||
def test(self, one, two):
|
||||
assert one == '1'
|
||||
assert two == '2'
|
||||
return 'it worked'
|
||||
|
||||
app = TestApp(Pecan(RootController()))
|
||||
r = app.get('/test/1/2')
|
||||
assert r.status_int == 200
|
||||
assert r.body == 'it worked'
|
||||
|
||||
def test_uri_to_parameter_mapping_with_validation(self):
|
||||
class TestSchema(Schema):
|
||||
one = validators.Int(not_empty=True)
|
||||
two = validators.Int(not_empty=True)
|
||||
|
||||
class RootController(object):
|
||||
@expose(schema=TestSchema())
|
||||
def test(self, one, two):
|
||||
assert request.validation_error is None
|
||||
assert one == 1
|
||||
assert two == 2
|
||||
return 'it worked'
|
||||
|
||||
@expose(schema=TestSchema())
|
||||
def fail(self, one, two):
|
||||
assert request.validation_error is not None
|
||||
assert one == 'one'
|
||||
assert two == 'two'
|
||||
return 'it failed'
|
||||
|
||||
app = TestApp(Pecan(RootController()))
|
||||
r = app.get('/test/1/2')
|
||||
assert r.status_int == 200
|
||||
assert r.body == 'it worked'
|
||||
|
||||
r = app.get('/fail/one/two')
|
||||
assert r.status_int == 200
|
||||
assert r.body == 'it failed'
|
||||
Reference in New Issue
Block a user