Serving Static Assets¶
This collection of recipes describes how to serve static assets in a variety of manners.
Serving File Content Dynamically¶
Usually you'll use a static view (via "config.add_static_view") to serve file content that lives on the filesystem. But sometimes files need to be composed and read from a nonstatic area, or composed on the fly by view code and served out (for example, a view callable might construct and return a PDF file or an image).
By way of example, here's a Pyramid application which serves a single static
file (a jpeg) when the URL /test.jpg
is executed:
1from pyramid.view import view_config
2from pyramid.config import Configurator
3from pyramid.response import FileResponse
4from paste.httpserver import serve
5
6@view_config(route_name='jpg')
7def test_page(request):
8 response = FileResponse(
9 '/home/chrism/groundhog1.jpg',
10 request=request,
11 content_type='image/jpeg'
12 )
13 return response
14
15if __name__ == '__main__':
16 config = Configurator()
17 config.add_route('jpg', '/test.jpg')
18 config.scan('__main__')
19 serve(config.make_wsgi_app())
Basically, use a pyramid.response.FileResponse
as the response object and
return it. Note that the request
and content_type
arguments are
optional. If request
is not supplied, any wsgi.file_wrapper
optimization supplied by your WSGI server will not be used when serving the
file. If content_type
is not supplied, it will be guessed using the
mimetypes
module (which uses the file extension); if it cannot be guessed
successfully, the application/octet-stream
content type will be used.
Serving a Single File from the Root¶
If you need to serve a single file such as /robots.txt
or
/favicon.ico
that must be served from the root, you cannot use a
static view to do it, as static views cannot serve files from the
root (a static view must have a nonempty prefix such as /static
). To
work around this limitation, create views "by hand" that serve up the raw
file data. Below is an example of creating two views: one serves up a
/favicon.ico
, the other serves up /robots.txt
.
At startup time, both files are read into memory from files on disk using plain Python. A Response object is created for each. This response is served by a view which hooks up the static file's URL.
1# this module = myapp.views
2
3import os
4
5from pyramid.response import Response
6from pyramid.view import view_config
7
8# _here = /app/location/myapp
9
10_here = os.path.dirname(__file__)
11
12# _icon = /app/location/myapp/static/favicon.ico
13
14_icon = open(os.path.join(
15 _here, 'static', 'favicon.ico')).read()
16_fi_response = Response(content_type='image/x-icon',
17 body=_icon)
18
19# _robots = /app/location/myapp/static/robots.txt
20
21_robots = open(os.path.join(
22 _here, 'static', 'robots.txt')).read()
23_robots_response = Response(content_type='text/plain',
24 body=_robots)
25
26@view_config(name='favicon.ico')
27def favicon_view(context, request):
28 return _fi_response
29
30@view_config(name='robots.txt')
31def robotstxt_view(context, request):
32 return _robots_response
Root-Relative Custom Static View (URL Dispatch Only)¶
The pyramid.static.static_view
helper class generates a Pyramid view
callable. This view callable can serve static assets from a directory. An
instance of this class is actually used by the
pyramid.config.Configurator.add_static_view()
configuration method, so
its behavior is almost exactly the same once it's configured.
警告
The following example will not work for applications that use
traversal, it will only work if you use URL dispatch
exclusively. The root-relative route we'll be registering will always be
matched before traversal takes place, subverting any views registered via
add_view
(at least those without a route_name
). A
pyramid.static.static_view
cannot be made root-relative when you
use traversal.
To serve files within a directory located on your filesystem at
/path/to/static/dir
as the result of a "catchall" route hanging from the
root that exists at the end of your routing table, create an instance of the
pyramid.static.static_view
class inside a static.py
file in your
application root as below:
from pyramid.static import static_view
www = static_view('/path/to/static/dir', use_subpath=True)
注釈
For better cross-system flexibility, use an asset
specification as the argument to pyramid.static.static_view
instead of a physical absolute filesystem path, e.g. mypackage:static
instead of /path/to/mypackage/static
.
Subsequently, you may wire the files that are served by this view up to be
accessible as /<filename>
using a configuration method in your
application's startup code:
# .. every other add_route and/or add_handler declaration should come
# before this one, as it will, by default, catch all requests
config.add_route('catchall_static', '/*subpath', 'myapp.static.www')
The special name *subpath
above is used by the
pyramid.static.static_view
view callable to signify the path of the
file relative to the directory you're serving.