summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris McDonough <chrism@plope.com>2010-12-24 22:26:16 -0500
committerChris McDonough <chrism@plope.com>2010-12-24 22:26:16 -0500
commit56db9ebbb2443f213cc38911c83de24a5abbb111 (patch)
tree8f988c293d2648217858e3f842c1caeffdd6319f
parent22533dbdc0f362eb680f1053bc707e9b00e9f717 (diff)
downloadpyramid-56db9ebbb2443f213cc38911c83de24a5abbb111.tar.gz
pyramid-56db9ebbb2443f213cc38911c83de24a5abbb111.tar.bz2
pyramid-56db9ebbb2443f213cc38911c83de24a5abbb111.zip
- Changed "Static Assets" narrative chapter: clarify that ``name`` represents
a prefix unless it's a URL, added an example of a root-relative static view fallback for URL dispatch, added an example of creating a simple view that returns the body of a file.
-rw-r--r--CHANGES.txt5
-rw-r--r--TODO.txt13
-rw-r--r--docs/narr/static.rst262
3 files changed, 163 insertions, 117 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index cb32825d5..db7cb991a 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -68,6 +68,11 @@ Documentation
- Add "Pyramid Provides More Than One Way to Do It" to Design Defense
documentation.
+- Changed "Static Assets" narrative chapter: clarify that ``name`` represents
+ a prefix unless it's a URL, added an example of a root-relative static view
+ fallback for URL dispatch, added an example of creating a simple view that
+ returns the body of a file.
+
1.0a7 (2010-12-20)
==================
diff --git a/TODO.txt b/TODO.txt
index f0b1e8b58..a220d78aa 100644
--- a/TODO.txt
+++ b/TODO.txt
@@ -14,23 +14,10 @@ Must-Have (before 1.0)
Should-Have
-----------
-- Fix add_static_view docs to mention: static views cannot be served from the
- root, that "name" really means "prefix", and that a non-URL prefix can be a
- path with slashes in it.
-
-- Add an example of serving a static asset from the root using a view.
-
-- Add an example of serving a static asset using a view by setting
- response.app_iter and the response content-type/content-disposition.
-
- Add an example of using a cascade to serve static assets from the root.
- Explore static file return from handler action using wsgiapp2 + fileapp.
-- Document ``config.add_route('catchall', '/*subpath',
- view=pyramid.views.static('some:asset/spec'))``, and explain that
- ``static`` requires ``subpath``.
-
- Static (URL-generation only) routes.
- Add narrative docs for wsgiapp and wsgiapp2.
diff --git a/docs/narr/static.rst b/docs/narr/static.rst
index 53564a632..e6be5fdff 100644
--- a/docs/narr/static.rst
+++ b/docs/narr/static.rst
@@ -15,18 +15,18 @@ Serving Static Assets
Use the :meth:`pyramid.config.Configurator.add_static_view` to instruct
:app:`Pyramid` to serve static assets such as JavaScript and CSS files. This
-mechanism makes static files available at a name relative to the application
-root URL, e.g. ``/static``.
+mechanism makes a directory of static files available at a name relative to
+the application root URL, e.g. ``/static`` or as an external URL.
-Note that the ``path`` provided to
-:meth:`pyramid.config.Configurator.add_static_view` may be a fully qualified
-:term:`asset specification`, or an *absolute path*.
+.. note:: `~pyramid.config.Configurator.add_static_view` cannot serve a
+ single file, nor can it serve a directory of static files directly
+ relative to the root URL of a :app:`Pyramid` application. For these
+ features, see :ref:`advanced_static`.
Here's an example of a use of
-:meth:`pyramid.config.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.
+:meth:`~pyramid.config.Configurator.add_static_view` that will serve files up
+from the ``/var/www/static`` directory of the computer which runs the
+:app:`Pyramid` application as URLs beneath the ``/static`` URL prefix.
.. code-block:: python
:linenos:
@@ -34,10 +34,30 @@ path.
# config is an instance of pyramid.config.Configurator
config.add_static_view(name='static', path='/var/www/static')
-Here's an example of :meth:`pyramid.config.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:`asset specification`.
+The ``name`` prepresents a URL *prefix*. In order for files that live in the
+``path`` directory to be served, a URL that requests one of them must begin
+with that prefix. In the example above, ``name`` is ``static``, and ``path``
+is ``/var/www/static``. In English, this means that you wish to serve the
+files that live in ``/var/www/static`` as sub-URLs of the ``/static`` URL
+prefix. Therefore, the file ``/var/www/static/foo.css`` will be returned
+when the user visits your application's URL ``/static/foo.css``.
+
+No authorization is ever required for users to visit files served by a static
+view added via :meth:`~pyramid.config.Configurator.add_static_view`. If you
+need "static" resources to be protected by authentication services, see
+:ref:`advanced_static`.
+
+A static directory named at ``path`` may contain subdirectories recursively,
+and any subdirectories may hold files; these will be resolved by the static
+view as you would expect. The ``Content-Type`` header returned by the static
+view for each particular type of file is dependent upon its file extension.
+
+Here's another example that uses an :term:`asset specification` instead of an
+absolute path as the ``path`` argument. To convince
+:meth:`pyramid.config.Configurator.add_static_view` to serve files up under
+the ``/static`` URL from the ``a/b/c/static`` directory of the Python package
+named ``some_package``, we can use a fully qualified :term:`asset
+specification` as the ``path``:
.. code-block:: python
:linenos:
@@ -45,22 +65,13 @@ qualified :term:`asset specification`.
# config is an instance of pyramid.config.Configurator
config.add_static_view(name='static', path='some_package:a/b/c/static')
-Whether you use for ``path`` a fully qualified asset specification, or an
-absolute path, when you place your static files on the filesystem in the
-directory represented as the ``path`` of the directive, you will then be able
-to view the static files in this directory via 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``, ``http://localhost:6543/static/foo.js`` will return 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.
-
-While the ``path`` argument can be a number of different things, the ``name``
-argument of the call to :meth:`pyramid.config.Configurator.add_static_view`
-can also be one of a number of things: a *view name* or a *URL*. The above
-examples have shown usage of the ``name`` argument as a view name. When
-``name`` is a *URL* (or any string with a slash (``/``) in it), static assets
+The ``path`` provided to :meth:`pyramid.config.Configurator.add_static_view`
+may be a fully qualified :term:`asset specification`, or an *absolute path*.
+
+Instead of representing a URL prefix, the ``name`` argument of a call to
+:meth:`pyramid.config.Configurator.add_static_view` can alternately be a
+*URL*. Each of examples we've seen so far have shown usage of the ``name``
+argument as a URL prefix. However, when ``name`` is a *URL*, static assets
can be served from an external webserver. In this mode, the ``name`` is used
as the URL prefix when generating a URL using :func:`pyramid.url.static_url`.
@@ -74,39 +85,22 @@ be fed a ``name`` argument which is ``http://example.com/images``:
config.add_static_view(name='http://example.com/images',
path='mypackage:images')
-Because :meth:`pyramid.config.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.config.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.config.Configurator.add_static_view`. Use of the
-:ref:`static_directive` ZCML directive is completely equivalent to using
-imperative configuration for the same purpose.
+Because :meth:`pyramid.config.Configurator.add_static_view` is provided with
+a ``name`` argument that is the URL ``http://example.com/images``, subsequent
+calls to :func:`pyramid.url.static_url` with paths that start with the
+``path`` argument passed to
+:meth:`pyramid.config.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.
.. 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.config.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.config.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.
+ The :ref:`static_directive` ZCML directive offers an declarative
+ equivalent to :meth:`pyramid.config.Configurator.add_static_view`. Use of
+ the :ref:`static_directive` ZCML directive is completely equivalent to
+ using imperative configuration for the same purpose.
.. index::
single: generating static asset urls
@@ -175,7 +169,8 @@ the the ``path`` given may be ``mypackage:images``:
.. code-block:: python
:linenos:
- config.add_static_view(name='http://example.com/images', path='mypackage:images')
+ config.add_static_view(name='http://example.com/images',
+ path='mypackage:images')
Under such a configuration, the URL generated by ``static_url`` for
assets which begin with ``mypackage:images`` will be prefixed with
@@ -187,24 +182,61 @@ assets which begin with ``mypackage:images`` will be prefixed with
static_url('mypackage:images/logo.png', request)
# -> http://example.com/images/logo.png
+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.config.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.config.Configurator.add_static_view` is a URL prefix). 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 prefix 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: static assets view
+.. _advanced_static:
+
Advanced: Serving Static Assets Using a View Callable
-----------------------------------------------------
For more flexibility, static assets can be served by a :term:`view callable`
-which you register manually. For example, you may want static assets to only
-be available when the :term:`context` is of a particular type, or when
-certain request headers are present.
-
-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 assets 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.
+which you register manually. For example, if you're using :term:`URL
+dispatch`, you may want static assets to only be available as a fallback if
+no previous route matches. Alternately, you might like to serve a particular
+static asset manually, because its download requires authentication.
+
+Note that you cannot use the :func:`pyramid.url.static_url` API to generate
+URLs against assets made accessible by registering a custom static view.
+
+Root-Relative Custom Static View (URL Dispatch Only)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The :class:`pyramid.view.static` 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
+:meth:`pyramid.config.Configurator.add_static_view` configuration method, so
+its behavior is almost exactly the same once it's configured.
+
+.. warning:: The following example *will not work* for applications that use
+ :term:`traversal`, it will only work if you use :term:`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
+ :class:`pyramid.view.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
+:class:`pyramid.view.static` class inside a ``static.py`` file in your
+application root as below.
.. ignore-next-block
.. code-block:: python
@@ -213,46 +245,68 @@ create an instance of the :class:`pyramid.view.static` class inside a
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:`asset specification`
- (e.g. ``anotherpackage:some/subdirectory``).
-
-Subsequently, you may wire this view up to be accessible as ``/static`` using
-the :mod:`pyramid.config.Configurator.add_view` method in your application's
-startup code against either the class or interface that represents your root
-resource object.
+.. note:: For better cross-system flexibility, use an :term:`asset
+ specification` as the argument to :class:`pyramid.view.static` 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.
.. code-block:: python
:linenos:
- config.add_view('mypackage.static.static_view', name='static',
- context='mypackage.resources.Root')
+ # .. every other add_route and/or add_handler declaration should come
+ # before this one, as it will, by default, catch all requests
-In this case, ``mypackage.resources.Root`` refers to the class of your
-:app:`Pyramid` application's resource tree.
+ config.add_route('catchall_static', '/*subpath', 'myapp.static.static_view')
-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 resource
-object in the resource tree. 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.
+The special name ``*subpath`` above is used by the
+:class:`pyramid.view.static` view callable to signify the path of the file
+relative to the directory you're serving.
-Note that you cannot use the :func:`pyramid.url.static_url` API to generate
-URLs against assets made accessible by registering a custom static view.
+Registering A View Callable to Serve a "Static" Asset
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+You can register a simple view callable to serve a single static asset. To
+do so, do things "by hand". First define the view callable.
-.. warning::
+.. code-block:: python
+ :linenos:
+
+ import os
+ from pyramid.view import view_config
+ from webob import Response
+
+ def favicon_view(request):
+ here = os.path.dirname(__file__)
+ icon = open(os.path.join(here, 'static', 'favicon.ico'))
+ return Response(content_type='image/x-icon', app_iter=icon)
+
+The above bit of code within ``favicon_view`` computes "here", which is a
+path relative to the Python file in which the function is defined. It then
+uses the Python ``open`` function to obtain a file handle to a file within
+"here" named ``static``, and returns a response using the open the file
+handle as the response's ``app_iter``. It makes sure to set the right
+content_type too.
+
+You might register such a view via configuration as a view callable that
+should be called as the result of a traversal:
+
+.. code-block:: python
+ :linenos:
+
+ config.add_view('myapp.views.favicon_view', name='favicon.ico')
+
+Or you might register it to be the view callable for a particular route:
+
+.. code-block:: python
+ :linenos:
- When adding a static view to your root object, you need to be careful that
- there are no resource objects contained in the root with the same key as
- the view name (e.g., ``static``). Resource objects take precedence during
- traversal, thus such a name collision will cause the resource to "shadow"
- your static view. To avoid this issue, and ensure that your root
- resource's ``__getitem__`` is never called when a static asset 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" (``@@``).
+ config.add_route('favicon', '/favicon.ico',
+ view='myapp.views.favicon_view')
+Because this is a simple view callable, it can be protected with a
+:term:`permission` or can be configured to respond under different
+circumstances using :term:`view predicate` arguments.