1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
|
Static Resources
================
:app:`Pyramid` makes it possible to serve up static
resources files from a directory on a filesystem. This chapter describes
how to configure :app:`Pyramid` to do so.
.. index::
single: add_static_view
.. _static_resources_section:
Serving Static Resources
------------------------
Use the :meth:`pyramid.configuration.Configurator.add_static_view` to
instruct :app:`Pyramid` to serve static resources such as JavaScript and CSS
files. This mechanism makes static files available at a name relative to the
application root URL, e.g. ``/static``.
Note that the ``path`` provided to
:meth:`pyramid.configuration.Configurator.add_static_view` may be a fully
qualified :term:`resource specification`, or an *absolute path*.
Here's an example of a use of
:meth:`pyramid.configuration.Configurator.add_static_view` that will serve
files up under the ``/static`` URL from the ``/var/www/static`` directory of
the computer which runs the :app:`Pyramid` application using an absolute
path.
.. code-block:: python
:linenos:
# config is an instance of pyramid.configuration.Configurator
config.add_static_view(name='static', path='/var/www/static')
Here's an example of
:meth:`pyramid.configuration.Configurator.add_static_view` that will serve
files up under the ``/static`` URL from the ``a/b/c/static`` directory of the
Python package named ``some_package`` using a fully qualified :term:`resource
specification`.
.. code-block:: python
:linenos:
# config is an instance of pyramid.configuration.Configurator
config.add_static_view(name='static', path='some_package:a/b/c/static')
Whether you use a fully qualified resource specification, or an absolute
path for ``path`` in the directive, it specifies a filesystem directory
where static files will be served from. Once you place files there, you
will then be able to view them from a browser at URLs prefixed with the
directive's ``name``. For instance, if the ``static`` directive's
``name`` is ``static``, and the static directive's ``path`` is
``/path/to/static/dir``, ``http://localhost:6543/static/foo.js`` will
serve the file ``/path/to/static/dir/foo.js``. The static directory may
contain subdirectories recursively, and any subdirectories may hold
files; these will be resolved by the static view as you would expect.
The ``name`` argument of the call to
:meth:`pyramid.configuration.Configurator.add_static_view` can be either
a *view name*, or a *URL*. In the above examples, the ``name`` argument
is a view name. When ``name`` is a *URL* (or any string with a slash
(``/``) in it), static resources can be served from an external
webserver. In this mode, the ``name`` is used as the URL prefix when
generating a URL using the :func:`pyramid.url.static_url` function.
For example, :meth:`pyramid.configuration.Configurator.add_static_view` may
be fed a ``name`` argument which is ``http://example.com/images``:
.. code-block:: python
:linenos:
# config is an instance of pyramid.configuration.Configurator
config.add_static_view(name='http://example.com/images',
path='mypackage:images')
Because :meth:`pyramid.configuration.Configurator.add_static_view` is
provided with a ``name`` argument that is the URL prefix
``http://example.com/images``, subsequent calls to
:func:`pyramid.url.static_url` with paths that start with the ``path``
argument passed to :meth:`pyramid.configuration.Configurator.add_static_view`
will generate a URL something like ``http://example.com/images/logo.png``. The
external webserver listening on ``example.com`` must be itself configured to
respond properly to such a request. The :func:`pyramid.url.static_url` API
is discussed in more detail later in this chapter.
The :ref:`static_directive` ZCML directive offers an declarative equivalent
to :meth:`pyramid.configuration.Configurator.add_static_view`. Use of the
:ref:`static_directive` ZCML directive is completely equivalent to using
imperative configuration for the same purpose.
.. note::
Using :func:`pyramid.url.static_url` in conjunction with a
:meth:`pyramid.configuration.Configurator.add_static_view` makes it
possible to put static media on a separate webserver during production (if
the ``name`` argument to
:meth:`pyramid.configuration.Configurator.add_static_view` is a URL),
while keeping static media package-internal and served by the development
webserver during development (if the ``name`` argument to
:meth:`pyramid.configuration.Configurator.add_static_view` is a view
name). To create such a circumstance, we suggest using the
:attr:`pyramid.registry.Registry.settings` API in conjunction with a
setting in the application ``.ini`` file named ``media_location``. Then
set the value of ``media_location`` to either a view name or a URL
depending on whether the application is being run in development or in
production (use a different `.ini`` file for production than you do for
development). This is just a suggestion for a pattern; any setting name
other than ``media_location`` could be used.
.. index::
single: generating static resource urls
single: static resource urls
.. _generating_static_resource_urls:
Generating Static Resource URLs
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When a :meth:`pyramid.configuration.Configurator.add_static_view` method is
used to register a static resource directory, a special helper API named
:func:`pyramid.url.static_url` can be used to generate the appropriate URL for a
package resource that lives in one of the directories named by the static
registration ``path`` attribute.
For example, let's assume you create a set of static declarations like so:
.. code-block:: python
:linenos:
config.add_static_view(name='static1', path='mypackage:resources/1')
config.add_static_view(name='static2', path='mypackage:resources/2')
These declarations create URL-accessible directories which have URLs that
begin with ``/static1`` and ``/static2``, respectively. The resources in
the ``resources/1`` directory of the ``mypackage`` package are consulted when
a user visits a URL which begins with ``/static1``, and the resources in the
``resources/2`` directory of the ``mypackage`` package are consulted when a
user visits a URL which begins with ``/static2``.
You needn't generate the URLs to static resources "by hand" in such a
configuration. Instead, use the :func:`pyramid.url.static_url` API
to generate them for you. For example:
.. code-block:: python
:linenos:
from pyramid.url import static_url
from pyramid.chameleon_zpt import render_template_to_response
def my_view(request):
css_url = static_url('mypackage:resources/1/foo.css', request)
js_url = static_url('mypackage:resources/2/foo.js', request)
return render_template_to_response('templates/my_template.pt',
css_url = css_url,
js_url = js_url)
If the request "application URL" of the running system is
``http://example.com``, the ``css_url`` generated above would be:
``http://example.com/static1/foo.css``. The ``js_url`` generated
above would be ``http://example.com/static2/foo.js``.
One benefit of using the :func:`pyramid.url.static_url` function rather than
constructing static URLs "by hand" is that if you need to change the ``name``
of a static URL declaration, the generated URLs will continue to resolve
properly after the rename.
URLs may also be generated by :func:`pyramid.url.static_url` to static
resources that live *outside* the :app:`Pyramid` application. This will
happen when the :meth:`pyramid.configuration.Configurator.add_static_view`
API associated with the path fed to :func:`pyramid.url.static_url` is a *URL*
instead of a view name. For example, the ``name`` argument may be
``http://example.com`` while the the ``path`` given may be
``mypackage:images``:
.. code-block:: python
:linenos:
config.add_static_view(name='http://example.com/images', path='mypackage:images')
Under such a configuration, the URL generated by ``static_url`` for
resources which begin with ``mypackage:images`` will be prefixed with
``http://example.com/images``:
.. code-block:: python
:linenos:
static_url('mypackage:images/logo.png', request)
# -> http://example.com/images/logo.png
.. index::
single: static resource view
Advanced: Serving Static Resources Using a View Callable
--------------------------------------------------------
For more flexibility, static resources can be served by a :term:`view
callable` which you register manually. For example, you may want
static resources to only be available when the :term:`context` of the
view is of a particular type, or when the request is of a particular
type.
The :class:`pyramid.view.static` helper class is used to perform
this task. This class creates an object that is capable acting as a
:app:`Pyramid` view callable which serves static resources from a
directory. For instance, to serve files within a directory located on
your filesystem at ``/path/to/static/dir`` from the URL path
``/static`` in your application, create an instance of the
:class:`pyramid.view.static` class inside a ``static.py`` file in
your application root as below.
.. ignore-next-block
.. code-block:: python
:linenos:
from pyramid.view import static
static_view = static('/path/to/static/dir')
.. note:: the argument to :class:`pyramid.view.static` can also be
a "here-relative" pathname, e.g. ``my/static`` (meaning relative to the
Python package of the module in which the view is being defined).
It can also be a :term:`resource specification`
(e.g. ``anotherpackage:some/subdirectory``).
Subsequently, you may wire this view up to be accessible as ``/static`` using
the :mod:`pyramid.configuration.Configurator.add_view` method in your
application's startup code against either the class or interface that
represents your root object.
.. code-block:: python
:linenos:
config.add_view('mypackage.static.static_view', name='static',
context='mypackage.models.Root')
In this case, ``mypackage.models.Root`` refers to the class of your
:app:`Pyramid` application's traversal root object.
The context argument above limits where the static view is accessible to
URL paths directly under the root object. If you omit the ``context``
argument, then ``static`` will be accessible as the static view against
any model object in the traversal graph. This will allow
``/static/foo.js`` to work, but it will also allow for
``/anything/static/foo.js`` too, as long as ``anything`` can be
resolved.
Note that you cannot use the :func:`pyramid.url.static_url` API to generate
URLs against resources made accessible by registering a custom static view.
.. warning::
When adding a static view to your root object, you need to be
careful that there are no model objects contained in the
root with the same key as the view name (e.g., ``static``).
Model objects take precedence during traversal,
thus such a name collision will cause the model to "shadow"
your static view. To avoid this issue, and ensure that your
root object's ``__getitem__`` is never
called when a static resource is requested, you can refer to them
unambiguously using the ``@@`` prefix (goggles) in their URLs.
For the above examples you could use '/@@static/foo.js'
instead of '/static/foo.js' to avoid such shadowing.
See :ref:`traversal_chapter` for information
about "goggles" (``@@``).
|