ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 02.01.2026

Просмотров: 2760

Скачиваний: 0

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

31.3. EXTENDING AN EXISTING APPLICATION

4config = Configurator()

5config.include(add_views)

6

 

7

def add_views(config):

8

config.add_view(’myapp.views.view1’, name=’view1’)

9config.add_view(’myapp.views.view2’, name=’view2’)

Doing this allows an integrator to maximally reuse the configuration statements that relate to your application by allowing him to selectively include or disinclude the configuration functions you’ve created from an “override package”.

Alternately, you can use ZCML for the purpose of making configuration extensible and overrideable. ZCML declarations that belong to an application can be overridden and extended by integrators as necessary in a similar fashion. If you use only ZCML to configure your application, it will automatically be maximally extensible without any manual effort. See pyramid_zcml for information about using ZCML.

31.2.1 Fundamental Plugpoints

The fundamental “plug points” of an application developed using Pyramid are routes, views, and assets. Routes are declarations made using the pyramid.config.Configurator.add_route() method. Views are declarations made using the pyramid.config.Configurator.add_view() method. Assets are files that are accessed by Pyramid using the pkg_resources API such as static files and templates via a asset specification. Other directives and configurator methods also deal in routes, views, and assets. For example, the add_handler directive of the pyramid_handlers package adds a single route, and some number of views.

31.3 Extending an Existing Application

The steps for extending an existing application depend largely on whether the application does or does not use configuration decorators and/or imperative code.

31.3.1 If The Application Has Configuration Decorations

You’ve inherited a Pyramid application which you’d like to extend or override that uses pyramid.view.view_config decorators or other configuration decoration decorators.

If you just want to extend the application, you can run a scan against the application’s package, then add additional configuration that registers more views or routes.

357

31. EXTENDING AN EXISTING PYRAMID APPLICATION

1 if __name__ == ’__main__’:

2config.scan(’someotherpackage’)

3config.add_view(’mypackage.views.myview’, name=’myview’)

If you want to override configuration in the application, you may need to run pyramid.config.Configurator.commit() after performing the scan of the original package, then add additional configuration that registers more views or routes which performs overrides.

1 if __name__ == ’__main__’:

2config.scan(’someotherpackage’)

3config.commit()

4config.add_view(’mypackage.views.myview’, name=’myview’)

Once this is done, you should be able to extend or override the application like any other (see Extending the Application).

You can alternately just prevent a scan from happening (by omitting any call to the pyramid.config.Configurator.scan() method). This will cause the decorators attached to objects in the target application to do nothing. At this point, you will need to convert all the configuration done in decorators into equivalent imperative configuration or ZCML and add that configuration or ZCML to a separate Python package as described in Extending the Application.

31.3.2 Extending the Application

To extend or override the behavior of an existing application, you will need to create a new package which includes the configuration of the old package, and you’ll perhaps need to create implementations of the types of things you’d like to override (such as views), which are referred to within the original package.

The general pattern for extending an existing application looks something like this:

Create a new Python package. The easiest way to do this is to create a new Pyramid application using the scaffold mechanism. See Creating the Project for more information.

In the new package, create Python files containing views and other overridden elements, such as templates and static assets as necessary.

Install the new package into the same Python environment as the original application (e.g. $myvenv/bin/python setup.py develop or $myvenv/bin/python setup.py install).

358


31.3. EXTENDING AN EXISTING APPLICATION

Change the main function in the new package’s __init__.py to include the original Pyramid application’s configuration functions via pyramid.config.Configurator.include() statements or a scan.

Wire the new views and assets created in the new package up using imperative registrations within the main function of the __init__.py file of the new application. These wiring should happen after including the configuration functions of the old application. These registrations will extend or override any registrations performed by the original application. See Overriding Views, Overriding Routes and Overriding Assets.

31.3.3 Overriding Views

The view configuration declarations you make which override application behavior will usually have the same view predicate attributes as the original you wish to override. These <view> declarations will point at “new” view code, in the override package you’ve created. The new view code itself will usually be cut-n-paste copies of view callables from the original application with slight tweaks.

For example, if the original application has the following configure_views configuration method:

1def configure_views(config):

2config.add_view(’theoriginalapp.views.theview’, name=’theview’)

You can override the first view configuration statement made by configure_views within the override package, after loading the original configuration function:

1 from pyramid.config import Configurator

2 from originalapp import configure_views

3

4 if __name == ’__main__’:

5config = Configurator()

6config.include(configure_views)

7config.add_view(’theoverrideapp.views.theview’, name=’theview’)

In this case, the theoriginalapp.views.theview view will never be executed. Instead, a new view, theoverrideapp.views.theview will be executed instead, when request circumstances dictate.

A similar pattern can be used to extend the application with add_view declarations. Just register a new view against some other set of predicates to make sure the URLs it implies are available on some other page rendering.

359

31. EXTENDING AN EXISTING PYRAMID APPLICATION

31.3.4 Overriding Routes

Route setup is currently typically performed in a sequence of ordered calls to add_route(). Because these calls are ordered relative to each other, and because this ordering is typically important, you should retain their relative ordering when performing an override. Typically, this means copying all the add_route statements into the override package’s file and changing them as necessary. Then disinclude any add_route statements from the original application.

31.3.5 Overriding Assets

Assets are files on the filesystem that

are accessible within a Python package.

An entire chap-

ter is devoted to assets: Static Assets.

Within this chapter is a section named

Overriding As-

sets. This section of that chapter describes in detail how to override package assets with other assets by using the pyramid.config.Configurator.override_asset() method. Add such override_asset calls to your override package’s __init__.py to perform overrides.

360



CHAPTER

THIRTYTWO

ADVANCED CONFIGURATION

To support application extensibility, the Pyramid Configurator, by default, detects configuration conflicts and allows you to include configuration imperatively from other packages or modules. It also, by default, performs configuration in two separate phases. This allows you to ignore relative configuration statement ordering in some circumstances.

32.1 Conflict Detection

Here’s a familiar example of one of the simplest Pyramid applications, configured imperatively:

1 from wsgiref.simple_server import make_server

2 from pyramid.config import Configurator

3 from pyramid.response import Response

4

5 def hello_world(request):

6return Response(’Hello world!’)

7

8 if __name__ == ’__main__’:

9config = Configurator()

10config.add_view(hello_world)

11app = config.make_wsgi_app()

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

13server.serve_forever()

When you start this application, all will be OK. However, what happens if we try to add another view to the configuration with the same set of predicate arguments as one we’ve already added?

361

32. ADVANCED CONFIGURATION

1

from wsgiref.simple_server import make_server

2

from pyramid.config import Configurator

3

from pyramid.response import Response

4

 

5

def hello_world(request):

6return Response(’Hello world!’)

7

8 def goodbye_world(request):

9return Response(’Goodbye world!’)

10

11if __name__ == ’__main__’:

12config = Configurator()

13

14 config.add_view(hello_world, name=’hello’)

15

16# conflicting view configuration

17config.add_view(goodbye_world, name=’hello’)

18

19app = config.make_wsgi_app()

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

21server.serve_forever()

The application now has two conflicting view configuration statements. When we try to start it again, it won’t start. Instead, we’ll receive a traceback that ends something like this:

1

Traceback (most recent call last):

2

File "app.py", line 12, in <module>

3app = config.make_wsgi_app()

4File "pyramid/config.py", line 839, in make_wsgi_app

5self.commit()

6File "pyramid/pyramid/config.py", line 473, in commit

7 self._ctx.execute_actions()

8... more code ...

9 pyramid.exceptions.ConfigurationConflictError:

10Conflicting configuration actions

11For: (’view’, None, ’’, None, <InterfaceClass pyramid.interfaces.IView>,

12None, None, None, None, None, False, None, None, None)

13Line 14 of file app.py in <module>: ’config.add_view(hello_world)’

14Line 17 of file app.py in <module>: ’config.add_view(goodbye_world)’

This traceback is trying to tell us:

• We’ve got conflicting information for a set of view configuration statements (The For: line).

362