Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
pyramid.pdf
Скачиваний:
10
Добавлен:
24.03.2015
Размер:
3.82 Mб
Скачать

29. USING HOOKS

When an alternate response object implementation is returned by a view callable, if that object asserts that it implements IResponse (via zope.interface.implementer(IResponse)) , an adapter needn’t be registered for the object; Pyramid will use it directly.

An IResponse adapter for webob.Response (as opposed to pyramid.response.Response) is registered by Pyramid by default at startup time, as by their nature, instances of this class (and instances of subclasses of the class) will natively provide IResponse. The adapter registered for webob.Response simply returns the response object.

Instead of using pyramid.config.Configurator.add_response_adapter(), you can use the pyramid.response.response_adapter decorator:

1

2

3

4

5

6

7

from pyramid.response import Response

from pyramid.response import response_adapter

@response_adapter(str)

def string_response_adapter(s): response = Response(s) return response

The above example, when scanned, has the same effect as:

config.add_response_adapter(string_response_adapter, str)

The response_adapter decorator will have no effect until activated by a scan.

29.11 Using a View Mapper

The default calling conventions for view callables are documented in the Views chapter. You can change the way users define view callables by employing a view mapper.

A view mapper is an object that accepts a set of keyword arguments and which returns a callable. The returned callable is called with the view callable object. The returned callable should itself return another callable which can be called with the “internal calling protocol” (context, request).

You can use a view mapper in a number of ways:

by setting a __view_mapper__ attribute (which is the view mapper object) on the view callable itself

330

29.11. USING A VIEW MAPPER

by passing the mapper object to pyramid.config.Configurator.add_view() (or its declarative/decorator equivalents) as the mapper argument.

by registering a default view mapper.

Here’s an example of a view mapper that emulates (somewhat) a Pylons “controller”. The mapper is initialized with some keyword arguments. Its __call__ method accepts the view object (which will be a class). It uses the attr keyword argument it is passed to determine which attribute should be used as an action method. The wrapper method it returns accepts (context, request) and returns the result of calling the action method with keyword arguments implied by the matchdict after popping the action out of it. This somewhat emulates the Pylons style of calling action methods with routing parameters pulled out of the route matching dict as keyword arguments.

1

# framework

2

 

3 class PylonsControllerViewMapper(object):

4 def __init__(self, **kw):

5self.kw = kw

6

7def __call__(self, view):

8attr = self.kw[’attr’]

9def wrapper(context, request):

10

matchdict = request.matchdict.copy()

11

matchdict.pop(’action’, None)

12

inst

=

view(request)

13

meth

=

getattr(inst, attr)

14return meth(**matchdict)

15return wrapper

16

17class BaseController(object):

18__view_mapper__ = PylonsControllerViewMapper

A user might make use of these framework components like so:

1

# user application

2

 

3

from pyramid.response import Response

4

from pyramid.config import Configurator

5

import pyramid_handlers

6

from wsgiref.simple_server import make_server

7

 

8

class MyController(BaseController):

9def index(self, id):

10 return Response(id)

11

331

29. USING HOOKS

12if __name__ == ’__main__’:

13config = Configurator()

14config.include(pyramid_handlers)

15config.add_handler(’one’, ’/{id}’, MyController, action=’index’)

16config.add_handler(’two’, ’/{action}/{id}’, MyController)

17server.make_server(’0.0.0.0’, 8080, config.make_wsgi_app())

18server.serve_forever()

The pyramid.config.Configurator.set_view_mapper() method can be used to set a default view mapper (overriding the superdefault view mapper used by Pyramid itself).

A single view registration can use a view mapper by passing the mapper as the mapper argument to add_view().

29.12 Registering Configuration Decorators

Decorators such as view_config don’t change the behavior of the functions or classes they’re decorating. Instead, when a scan is performed, a modified version of the function or class is registered with Pyramid.

You may wish to have your own decorators that offer such behaviour. This is possible by using the Venusian package in the same way that it is used by Pyramid.

By way of example, let’s suppose you want to write a decorator that registers the function it wraps with a Zope Component Architecture “utility” within the application registry provided by Pyramid. The application registry and the utility inside the registry is likely only to be available once your application’s configuration is at least partially completed. A normal decorator would fail as it would be executed before the configuration had even begun.

However, using Venusian, the decorator could be written as follows:

1

2

3

4

5

6

7

8

9

10

import venusian

from mypackage.interfaces import IMyUtility

class registerFunction(object):

def __init__(self, path): self.path = path

def register(self, scanner, name, wrapped): registry = scanner.config.registry

332

29.12. REGISTERING CONFIGURATION DECORATORS

11

12

13

14

15

16

registry.getUtility(IMyUtility).register( self.path, wrapped)

def __call__(self, wrapped): venusian.attach(wrapped, self.register) return wrapped

This decorator could then be used to register functions throughout your code:

1

2

3

@registerFunction(’/some/path’) def my_function():

do_stuff()

However, the utility would only be looked up when a scan was performed, enabling you to set up the utility in advance:

1

from zope.interface import implementer

2

 

3

from wsgiref.simple_server import make_server

4

from pyramid.config import Configurator

5

from mypackage.interfaces import IMyUtility

6

 

7

@implementer(IMyUtility)

8

class UtilityImplementation:

9

10def __init__(self):

11self.registrations = {}

12

13def register(self, path, callable_):

14self.registrations[path] = callable_

15

16if __name__ == ’__main__’:

17config = Configurator()

18config.registry.registerUtility(UtilityImplementation())

19config.scan()

20app = config.make_wsgi_app()

21server = make_server(’0.0.0.0’, 8080, app)

22server.serve_forever()

For full details, please read the Venusian documentation.

333

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]