commit | author | age
|
9ec2d6
|
1 |
.. index:: |
CM |
2 |
single: application configuration |
41e3bf
|
3 |
|
590fe7
|
4 |
.. _configuration_narr: |
CM |
5 |
|
553a94
|
6 |
Application Configuration |
9ec2d6
|
7 |
========================= |
41e3bf
|
8 |
|
be9bbf
|
9 |
Most people already understand "configuration" as settings that influence the |
553a94
|
10 |
operation of an application. For instance, it's easy to think of the values in |
SP |
11 |
a ``.ini`` file parsed at application startup time as "configuration". However, |
|
12 |
if you're reasonably open-minded, it's easy to think of *code* as configuration |
|
13 |
too. Since Pyramid, like most other web application platforms, is a |
|
14 |
*framework*, it calls into code that you write (as opposed to a *library*, |
|
15 |
which is code that exists purely for you to call). The act of plugging |
|
16 |
application code that you've written into :app:`Pyramid` is also referred to |
|
17 |
within this documentation as "configuration"; you are configuring |
be9bbf
|
18 |
:app:`Pyramid` to call the code that makes up your application. |
41e3bf
|
19 |
|
1a768e
|
20 |
.. seealso:: |
KOP |
21 |
For information on ``.ini`` files for Pyramid applications see the |
|
22 |
:ref:`startup_chapter` chapter. |
|
23 |
|
553a94
|
24 |
There are two ways to configure a :app:`Pyramid` application: :term:`imperative |
SP |
25 |
configuration` and :term:`declarative configuration`. Both are described below. |
4e1199
|
26 |
|
8c56ae
|
27 |
.. index:: |
c5f24b
|
28 |
single: imperative configuration |
8c56ae
|
29 |
|
9ec2d6
|
30 |
.. _imperative_configuration: |
f6c149
|
31 |
|
9ec2d6
|
32 |
Imperative Configuration |
CM |
33 |
------------------------ |
41e3bf
|
34 |
|
553a94
|
35 |
"Imperative configuration" just means configuration done by Python statements, |
SP |
36 |
one after the next. Here's one of the simplest :app:`Pyramid` applications, |
|
37 |
configured imperatively: |
41e3bf
|
38 |
|
CM |
39 |
.. code-block:: python |
|
40 |
:linenos: |
|
41 |
|
10f1b5
|
42 |
from wsgiref.simple_server import make_server |
d7f259
|
43 |
from pyramid.config import Configurator |
94b889
|
44 |
from pyramid.response import Response |
41e3bf
|
45 |
|
CM |
46 |
def hello_world(request): |
|
47 |
return Response('Hello world!') |
|
48 |
|
|
49 |
if __name__ == '__main__': |
d91e5d
|
50 |
with Configurator() as config: |
SP |
51 |
config.add_view(hello_world) |
|
52 |
app = config.make_wsgi_app() |
10f1b5
|
53 |
server = make_server('0.0.0.0', 8080, app) |
CM |
54 |
server.serve_forever() |
41e3bf
|
55 |
|
614f00
|
56 |
We won't talk much about what this application does yet. Just note that the |
f89437
|
57 |
configuration statements take place underneath the ``if __name__ == |
614f00
|
58 |
'__main__':`` stanza in the form of method calls on a :term:`Configurator` |
553a94
|
59 |
object (e.g., ``config.add_view(...)``). These statements take place one after |
SP |
60 |
the other, and are executed in order, so the full power of Python, including |
|
61 |
conditionals, can be employed in this mode of configuration. |
f6c149
|
62 |
|
8c56ae
|
63 |
.. index:: |
197f0c
|
64 |
single: view_config |
c5f24b
|
65 |
single: configuration decoration |
CM |
66 |
single: code scanning |
f6c149
|
67 |
|
9ec2d6
|
68 |
.. _decorations_and_code_scanning: |
13c923
|
69 |
|
4e1199
|
70 |
Declarative Configuration |
CM |
71 |
------------------------- |
13c923
|
72 |
|
4e1199
|
73 |
It's sometimes painful to have all configuration done by imperative code, |
553a94
|
74 |
because often the code for a single application may live in many files. If the |
SP |
75 |
configuration is centralized in one place, you'll need to have at least two |
|
76 |
files open at once to see the "big picture": the file that represents the |
|
77 |
configuration, and the file that contains the implementation objects referenced |
|
78 |
by the configuration. To avoid this, :app:`Pyramid` allows you to insert |
|
79 |
:term:`configuration decoration` statements very close to code that is referred |
|
80 |
to by the declaration itself. For example: |
f6c149
|
81 |
|
9ec2d6
|
82 |
.. code-block:: python |
CM |
83 |
:linenos: |
f6c149
|
84 |
|
94b889
|
85 |
from pyramid.response import Response |
197f0c
|
86 |
from pyramid.view import view_config |
4c4c5a
|
87 |
|
197f0c
|
88 |
@view_config(name='hello', request_method='GET') |
9ec2d6
|
89 |
def hello(request): |
CM |
90 |
return Response('Hello') |
b68f6c
|
91 |
|
553a94
|
92 |
The mere existence of configuration decoration doesn't cause any configuration |
SP |
93 |
registration to be performed. Before it has any effect on the configuration of |
|
94 |
a :app:`Pyramid` application, a configuration decoration within application |
|
95 |
code must be found through a process known as a :term:`scan`. |
de449d
|
96 |
|
cad9ce
|
97 |
For example, the :class:`pyramid.view.view_config` decorator in the code |
553a94
|
98 |
example above adds an attribute to the ``hello`` function, making it available |
SP |
99 |
for a :term:`scan` to find it later. |
9ec2d6
|
100 |
|
553a94
|
101 |
A :term:`scan` of a :term:`module` or a :term:`package` and its subpackages for |
SP |
102 |
decorations happens when the :meth:`pyramid.config.Configurator.scan` method is |
|
103 |
invoked: scanning implies searching for configuration declarations in a package |
|
104 |
and its subpackages. For example: |
9ec2d6
|
105 |
|
6a4c6c
|
106 |
.. code-block:: python |
TL |
107 |
:linenos: |
9ec2d6
|
108 |
|
6a4c6c
|
109 |
from wsgiref.simple_server import make_server |
TL |
110 |
from pyramid.config import Configurator |
|
111 |
from pyramid.response import Response |
|
112 |
from pyramid.view import view_config |
9ec2d6
|
113 |
|
6a4c6c
|
114 |
@view_config() |
TL |
115 |
def hello(request): |
|
116 |
return Response('Hello') |
9ec2d6
|
117 |
|
6a4c6c
|
118 |
if __name__ == '__main__': |
d91e5d
|
119 |
with Configurator() as config: |
SP |
120 |
config.scan() |
|
121 |
app = config.make_wsgi_app() |
6a4c6c
|
122 |
server = make_server('0.0.0.0', 8080, app) |
TL |
123 |
server.serve_forever() |
9ec2d6
|
124 |
|
cad9ce
|
125 |
The scanning machinery imports each module and subpackage in a package or |
553a94
|
126 |
module recursively, looking for special attributes attached to objects defined |
SP |
127 |
within a module. These special attributes are typically attached to code via |
|
128 |
the use of a :term:`decorator`. For example, the |
70acd2
|
129 |
:class:`~pyramid.view.view_config` decorator can be attached to a function or |
cad9ce
|
130 |
instance method. |
9ec2d6
|
131 |
|
553a94
|
132 |
Once scanning is invoked, and :term:`configuration decoration` is found by the |
SP |
133 |
scanner, a set of calls are made to a :term:`Configurator` on your behalf. |
|
134 |
These calls replace the need to add imperative configuration statements that |
|
135 |
don't live near the code being configured. |
9ec2d6
|
136 |
|
4e1199
|
137 |
The combination of :term:`configuration decoration` and the invocation of a |
CM |
138 |
:term:`scan` is collectively known as :term:`declarative configuration`. |
|
139 |
|
cad9ce
|
140 |
In the example above, the scanner translates the arguments to |
70acd2
|
141 |
:class:`~pyramid.view.view_config` into a call to the |
cad9ce
|
142 |
:meth:`pyramid.config.Configurator.add_view` method, effectively: |
9ec2d6
|
143 |
|
CM |
144 |
.. code-block:: python |
|
145 |
|
|
146 |
config.add_view(hello) |
|
147 |
|
be9bbf
|
148 |
Summary |
CM |
149 |
------- |
|
150 |
|
553a94
|
151 |
There are two ways to configure a :app:`Pyramid` application: declaratively and |
SP |
152 |
imperatively. You can choose the mode with which you're most comfortable; both |
|
153 |
are completely equivalent. Examples in this documentation will use both modes |
|
154 |
interchangeably. |