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):
|
def route(self, node, path):
|
||||||
path = path.split('/')[1:]
|
path = path.split('/')[1:]
|
||||||
node, remainder = lookup_controller(node, path)
|
node, remainder = lookup_controller(node, path)
|
||||||
return node
|
return node, remainder
|
||||||
|
|
||||||
def handle_security(self, controller):
|
def handle_security(self, controller):
|
||||||
if controller.pecan.get('secured', False):
|
if controller.pecan.get('secured', False):
|
||||||
@@ -90,11 +90,20 @@ class Pecan(object):
|
|||||||
for hook in state.hooks:
|
for hook in state.hooks:
|
||||||
getattr(hook, hook_type)(*args)
|
getattr(hook, hook_type)(*args)
|
||||||
|
|
||||||
def get_params(self, all_params, argspec):
|
def get_params(self, all_params, remainder, argspec):
|
||||||
valid_params = dict()
|
valid_params = dict()
|
||||||
|
|
||||||
|
# handle params that are POST or GET variables first
|
||||||
for param_name, param_value in all_params.iteritems():
|
for param_name, param_value in all_params.iteritems():
|
||||||
if param_name in argspec.args:
|
if param_name in argspec.args:
|
||||||
valid_params[param_name] = param_value
|
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
|
return valid_params
|
||||||
|
|
||||||
def validate(self, schema, params=None, json=False):
|
def validate(self, schema, params=None, json=False):
|
||||||
@@ -111,7 +120,7 @@ class Pecan(object):
|
|||||||
if '.' in path.split('/')[-1]:
|
if '.' in path.split('/')[-1]:
|
||||||
path, format = path.split('.')
|
path, format = path.split('.')
|
||||||
content_type = self.get_content_type(format)
|
content_type = self.get_content_type(format)
|
||||||
controller = self.route(self.root, path)
|
controller, remainder = self.route(self.root, path)
|
||||||
|
|
||||||
# determine content type
|
# determine content type
|
||||||
if content_type is None:
|
if content_type is None:
|
||||||
@@ -129,6 +138,7 @@ class Pecan(object):
|
|||||||
# fetch and validate any parameters
|
# fetch and validate any parameters
|
||||||
params = self.get_params(
|
params = self.get_params(
|
||||||
dict(state.request.str_params),
|
dict(state.request.str_params),
|
||||||
|
remainder,
|
||||||
controller.pecan['argspec']
|
controller.pecan['argspec']
|
||||||
)
|
)
|
||||||
if 'schema' in controller.pecan:
|
if 'schema' in controller.pecan:
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
from pecan import Pecan, expose, request, response, redirect
|
from pecan import Pecan, expose, request, response, redirect
|
||||||
from webtest import TestApp
|
from webtest import TestApp
|
||||||
|
from formencode import Schema, validators
|
||||||
|
|
||||||
|
|
||||||
class TestBase(object):
|
class TestBase(object):
|
||||||
|
|
||||||
@@ -193,3 +195,45 @@ class TestEngines(object):
|
|||||||
r = r.follow()
|
r = r.follow()
|
||||||
assert r.status_int == 200
|
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