使用视图映射器将查询参数作为关键字参数传递¶
Pyramid 支持“视图映射器”的概念。见 Using a View Mapper 有关视图映射器的常规信息。您可以使用视图映射器来支持另一种方便调用约定,在该约定中,您允许视图可调用文件命名从request.params字典中获取的额外必需和可选参数。例如,不是:
1@view_config()
2def aview(request):
3 name = request.params['name']
4 value = request.params.get('value', 'default')
5 ...
使用特殊的视图映射器,可以将其定义为:
@view_config(mapper=MapplyViewMapper)
def aview(request, name, value='default'):
...
The below code implements the MapplyViewMapper
. It works as a mapper for function view callables and method view callables:
1import inspect
2import sys
3
4from pyramid.view import view_config
5from pyramid.response import Response
6from pyramid.config import Configurator
7from waitress import serve
8
9PY3 = sys.version_info[0] == 3
10
11if PY3:
12 im_func = '__func__'
13 func_defaults = '__defaults__'
14 func_code = '__code__'
15else:
16 im_func = 'im_func'
17 func_defaults = 'func_defaults'
18 func_code = 'func_code'
19
20def mapply(ob, positional, keyword):
21
22 f = ob
23 im = False
24
25 if hasattr(f, im_func):
26 im = True
27
28 if im:
29 f = getattr(f, im_func)
30 c = getattr(f, func_code)
31 defaults = getattr(f, func_defaults)
32 names = c.co_varnames[1:c.co_argcount]
33 else:
34 defaults = getattr(f, func_defaults)
35 c = getattr(f, func_code)
36 names = c.co_varnames[:c.co_argcount]
37
38 nargs = len(names)
39 args = []
40 if positional:
41 positional = list(positional)
42 if len(positional) > nargs:
43 raise TypeError('too many arguments')
44 args = positional
45
46 get = keyword.get
47 nrequired = len(names) - (len(defaults or ()))
48 for index in range(len(args), len(names)):
49 name = names[index]
50 v = get(name, args)
51 if v is args:
52 if index < nrequired:
53 raise TypeError('argument %s was omitted' % name)
54 else:
55 v = defaults[index-nrequired]
56 args.append(v)
57
58 args = tuple(args)
59 return ob(*args)
60
61
62class MapplyViewMapper(object):
63 def __init__(self, **kw):
64 self.attr = kw.get('attr')
65
66 def __call__(self, view):
67 def wrapper(context, request):
68 keywords = dict(request.params.items())
69 if inspect.isclass(view):
70 inst = view(request)
71 meth = getattr(inst, self.attr)
72 response = mapply(meth, (), keywords)
73 else:
74 # it's a function
75 response = mapply(view, (request,), keywords)
76 return response
77
78 return wrapper
79
80@view_config(name='function', mapper=MapplyViewMapper)
81def view_function(request, one, two=False):
82 return Response('one: %s, two: %s' % (one, two))
83
84class ViewClass(object):
85 __view_mapper__ = MapplyViewMapper
86 def __init__(self, request):
87 self.request = request
88
89 @view_config(name='method')
90 def view_method(self, one, two=False):
91 return Response('one: %s, two: %s' % (one, two))
92
93if __name__ == '__main__':
94 config = Configurator()
95 config.scan('.')
96 app = config.make_wsgi_app()
97 serve(app)
98
99# http://localhost:8080/function --> (exception; no "one" arg supplied)
100
101# http://localhost:8080/function?one=1 --> one: '1', two: False
102
103# http://localhost:8080/function?one=1&two=2 --> one: '1', two: '2'
104
105# http://localhost:8080/method --> (exception; no "one" arg supplied)
106
107# http://localhost:8080/method?one=1 --> one: '1', two: False
108
109# http://localhost:8080/method?one=1&two=2 --> one: '1', two: '2'