single: application configuration
Most people already understand "configuration" as settings that influence the operation of an application. For instance, it's easy to think of the values in a .ini
file parsed at application startup time as "configuration". However, if you're reasonably open-minded, it's easy to think of code as configuration too. Since Pyramid, like most other web application platforms, is a framework, it calls into code that you write (as opposed to a library, which is code that exists purely for you to call). The act of plugging application code that you've written into Pyramid
is also referred to within this documentation as "configuration"; you are configuring Pyramid
to call the code that makes up your application.
For information on .ini
files for Pyramid applications see the startup_chapter
chapter.
There are two ways to configure a Pyramid
application: imperative
configuration
and declarative configuration
. Both are described below.
single: imperative configuration
"Imperative configuration" just means configuration done by Python statements, one after the next. Here's one of the simplest Pyramid
applications, configured imperatively:
from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response
def hello_world(request):
return Response('Hello world!')
if __name__ == '__main__':
with Configurator() as config:
config.add_route('hello', '/')
config.add_view(hello_world, route_name='hello')
app = config.make_wsgi_app()
server = make_server('0.0.0.0', 6543, app)
server.serve_forever()
We won't talk much about what this application does yet. Just note that the configuration statements take place underneath the if __name__ == '__main__':
stanza in the form of method calls on a Configurator
object (e.g., config.add_view(...)
). These statements take place one after the other, and are executed in order, so the full power of Python, including conditionals, can be employed in this mode of configuration.
single: view_config single: configuration decoration single: code scanning
It's sometimes painful to have all configuration done by imperative code, because often the code for a single application may live in many files. If the configuration is centralized in one place, you'll need to have at least two files open at once to see the "big picture": the file that represents the configuration, and the file that contains the implementation objects referenced by the configuration. To avoid this, Pyramid
allows you to insert configuration decoration
statements very close to code that is referred to by the declaration itself. For example:
from pyramid.response import Response
from pyramid.view import view_config
@view_config(route_name='hello', request_method='GET')
def hello_world(request):
return Response('Hello World!')
The mere existence of configuration decoration doesn't cause any configuration registration to be performed. Before it has any effect on the configuration of a Pyramid
application, a configuration decoration within application code must be found through a process known as a scan
.
For example, the pyramid.view.view_config
decorator in the code example above adds an attribute to the hello_world
function, making it available for a scan
to find it later.
A scan
of a module
or a package
and its subpackages for decorations happens when the pyramid.config.Configurator.scan
method is invoked: scanning implies searching for configuration declarations in a package and its subpackages. For example:
from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response
from pyramid.view import view_config
@view_config(route_name='hello', request_method='GET')
def hello_world(request):
return Response('Hello World!')
if __name__ == '__main__':
with Configurator() as config:
config.add_route('hello', '/')
config.scan()
app = config.make_wsgi_app()
server = make_server('0.0.0.0', 6543, app)
server.serve_forever()
The scanning machinery imports each module and subpackage in a package or module recursively, looking for special attributes attached to objects defined within a module. These special attributes are typically attached to code via the use of a decorator
. For example, the ~pyramid.view.view_config
decorator can be attached to a function or instance method.
Once scanning is invoked, and configuration decoration
is found by the scanner, a set of calls are made to a Configurator
on your behalf. These calls replace the need to add imperative configuration statements that don't live near the code being configured.
The combination of configuration decoration
and the invocation of a scan
is collectively known as declarative configuration
.
In the example above, the scanner translates the arguments to ~pyramid.view.view_config
into a call to the pyramid.config.Configurator.add_view
method, effectively:
config.add_view(hello_world, route_name='hello',
request_method='GET')
There are two ways to configure a Pyramid
application: declaratively and imperatively. You can choose the mode with which you're most comfortable; both are completely equivalent. Examples in this documentation will use both modes interchangeably.