CHANGES.txt | ●●●●● patch | view | raw | blame | history | |
docs/index.rst | ●●●●● patch | view | raw | blame | history | |
docs/latexindex.rst | ●●●●● patch | view | raw | blame | history | |
docs/narr/firstapp.rst | ●●●●● patch | view | raw | blame | history | |
docs/narr/renderers.rst | ●●●●● patch | view | raw | blame | history | |
docs/narr/traversal.rst | ●●●●● patch | view | raw | blame | history | |
docs/narr/urldispatch.rst | ●●●●● patch | view | raw | blame | history | |
docs/narr/viewconfig.rst | ●●●●● patch | view | raw | blame | history | |
docs/narr/views.rst | ●●●●● patch | view | raw | blame | history |
CHANGES.txt
@@ -6,6 +6,10 @@ - Fixed two typos in wiki2 (SQLA + URL Dispatch) tutorial. - Reordered chapters in narrative section for better new user friendliness. - Added more indexing markers to sections in documentation. 1.1b4 (2011-07-18) ================== docs/index.rst
@@ -43,24 +43,24 @@ narr/project narr/startup narr/urldispatch narr/muchadoabouttraversal narr/traversal narr/views narr/renderers narr/templates narr/viewconfig narr/resources narr/assets narr/webob narr/sessions narr/security narr/hybrid narr/i18n narr/vhosting narr/events narr/environment narr/commandline narr/i18n narr/vhosting narr/testing narr/resources narr/muchadoabouttraversal narr/traversal narr/security narr/hybrid narr/hooks narr/advconfig narr/extending docs/latexindex.rst
@@ -32,23 +32,24 @@ narr/firstapp narr/project narr/urldispatch narr/muchadoabouttraversal narr/traversal narr/views narr/renderers narr/templates narr/viewconfig narr/resources narr/assets narr/webob narr/sessions narr/security narr/hybrid narr/i18n narr/vhosting narr/events narr/environment narr/commandline narr/i18n narr/vhosting narr/testing narr/resources narr/muchadoabouttraversal narr/traversal narr/security narr/hybrid narr/hooks narr/advconfig narr/extending docs/narr/firstapp.rst
@@ -322,6 +322,3 @@ For more information about :term:`view configuration`, see :ref:`view_config_chapter`. An example of using *declarative* configuration (:term:`ZCML`) instead of imperative configuration to create a similar "hello world" is available within the documentation for :term:`pyramid_zcml`. docs/narr/renderers.rst
@@ -3,10 +3,10 @@ Renderers ========= A view needn't *always* return a :term:`Response` object. If a view happens to return something which does not implement the Pyramid Response interface, :app:`Pyramid` will attempt to use a :term:`renderer` to construct a response. For example: A view callable needn't *always* return a :term:`Response` object. If a view happens to return something which does not implement the Pyramid Response interface, :app:`Pyramid` will attempt to use a :term:`renderer` to construct a response. For example: .. code-block:: python :linenos: docs/narr/traversal.rst
@@ -456,6 +456,103 @@ -specific request attributes are also available as described in :ref:`special_request_attributes`. .. index:: single: resource interfaces .. _using_resource_interfaces: Using Resource Interfaces In View Configuration ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Instead of registering your views with a ``context`` that names a Python resource *class*, you can optionally register a view callable with a ``context`` which is an :term:`interface`. An interface can be attached arbitrarily to any resource object. View lookup treats context interfaces specially, and therefore the identity of a resource can be divorced from that of the class which implements it. As a result, associating a view with an interface can provide more flexibility for sharing a single view between two or more different implementations of a resource type. For example, if two resource objects of different Python class types share the same interface, you can use the same view configuration to specify both of them as a ``context``. In order to make use of interfaces in your application during view dispatch, you must create an interface and mark up your resource classes or instances with interface declarations that refer to this interface. To attach an interface to a resource *class*, you define the interface and use the :func:`zope.interface.implements` function to associate the interface with the class. .. code-block:: python :linenos: from zope.interface import Interface from zope.interface import implements class IHello(Interface): """ A marker interface """ class Hello(object): implements(IHello) To attach an interface to a resource *instance*, you define the interface and use the :func:`zope.interface.alsoProvides` function to associate the interface with the instance. This function mutates the instance in such a way that the interface is attached to it. .. code-block:: python :linenos: from zope.interface import Interface from zope.interface import alsoProvides class IHello(Interface): """ A marker interface """ class Hello(object): pass def make_hello(): hello = Hello() alsoProvides(hello, IHello) return hello Regardless of how you associate an interface, with a resource instance, or a resource class, the resulting code to associate that interface with a view callable is the same. Assuming the above code that defines an ``IHello`` interface lives in the root of your application, and its module is named "resources.py", the interface declaration below will associate the ``mypackage.views.hello_world`` view with resources that implement, or provide, this interface. .. code-block:: python :linenos: # config is an instance of pyramid.config.Configurator config.add_view('mypackage.views.hello_world', name='hello.html', context='mypackage.resources.IHello') Any time a resource that is determined to be the :term:`context` provides this interface, and a view named ``hello.html`` is looked up against it as per the URL, the ``mypackage.views.hello_world`` view callable will be invoked. Note, in cases where a view is registered against a resource class, and a view is also registered against an interface that the resource class implements, an ambiguity arises. Views registered for the resource class take precedence over any views registered for any interface the resource class implements. Thus, if one view configuration names a ``context`` of both the class type of a resource, and another view configuration names a ``context`` of interface implemented by the resource's class, and both view configurations are otherwise identical, the view registered for the context's class will "win". For more information about defining resources with interfaces for use within view configuration, see :ref:`resources_which_implement_interfaces`. References ---------- docs/narr/urldispatch.rst
@@ -6,28 +6,12 @@ URL Dispatch ============ :term:`URL dispatch` provides a simple way to map URLs to :term:`view` code using a simple pattern matching language. An ordered set of patterns is checked one-by-one. If one of the patterns matches the path information associated with a request, a particular :term:`view callable` is invoked. :term:`URL dispatch` is one of two ways to perform :term:`resource location` in :app:`Pyramid`; the other way is to use :term:`traversal`. If no route is matched using :term:`URL dispatch`, :app:`Pyramid` falls back to :term:`traversal` to handle the :term:`request`. It is the responsibility of the :term:`resource location` subsystem (i.e., :term:`URL dispatch` or :term:`traversal`) to find the resource object that is the :term:`context` of the :term:`request`. Once the :term:`context` is determined, :term:`view lookup` is then responsible for finding and invoking a :term:`view callable`. A view callable is a specific bit of code, defined in your application, that receives the :term:`request` and returns a :term:`response` object. Where appropriate, we will describe how view lookup interacts with :term:`resource location`. The :ref:`view_config_chapter` chapter describes the details of :term:`view lookup`. :term:`URL dispatch` provides a simple way to map URLs to :term:`view` code using a simple pattern matching language. An ordered set of patterns is checked one-by-one. If one of the patterns matches the path information associated with a request, a particular :term:`view callable` is invoked. A view callable is a specific bit of code, defined in your application, that receives the :term:`request` and returns a :term:`response` object. High-Level Operational Overview ------------------------------- @@ -37,18 +21,11 @@ matching patterns present in a *route map*. If any route pattern matches the information in the :term:`request`, :app:`Pyramid` will invoke :term:`view lookup` using a :term:`context` resource generated by the route match. :app:`Pyramid` will invoke :term:`view lookup` to find a matching view. However, if no route pattern matches the information in the :term:`request` provided to :app:`Pyramid`, it will fail over to using :term:`traversal` to perform resource location and view lookup. Technically, URL dispatch is a :term:`resource location` mechanism (it finds a context object). But ironically, using URL dispatch (instead of :term:`traversal`) allows you to avoid thinking about your application in terms of "resources" entirely, because it allows you to directly map a :term:`view callable` to a route. If no route pattern in the route map matches the information in the :term:`request` provided in your application, :app:`Pyramid` will fail over to using :term:`traversal` to perform resource location and view lookup. .. index:: single: route configuration @@ -89,8 +66,8 @@ When a :term:`view callable` added to the configuration by way of :meth:`~pyramid.config.Configurator.add_view` bcomes associated with a route via its ``route_name`` predicate, that view callable will always be found and invoked when the associated route pattern matches during a request. via its ``route_name`` predicate, that view callable will always be found and invoked when the associated route pattern matches during a request. More commonly, you will not use any ``add_view`` statements in your project's "setup" code, instead only using ``add_route`` statements using a @@ -323,12 +300,11 @@ Route configuration declarations are evaluated in a specific order when a request enters the system. As a result, the order of route configuration declarations is very important. The order that routes declarations are evaluated is the order in which they are added to the application at startup time. This is unlike :term:`traversal`, which depends on emergent behavior which happens as a result of traversing a resource tree. declarations is very important. The order that routes declarations are evaluated is the order in which they are added to the application at startup time. (This is unlike a different way of mapping URLs to code that :app:`Pyramid` provides, named :term:`traversal`, which does not depend on pattern ordering). For routes added via the :mod:`~pyramid.config.Configurator.add_route` method, the order that routes are evaluated is the order in which they are added to @@ -551,27 +527,30 @@ The main purpose of route configuration is to match (or not match) the ``PATH_INFO`` present in the WSGI environment provided during a request against a URL path pattern. against a URL path pattern. ``PATH_INFO`` represents the path portion of the URL that was requested. The way that :app:`Pyramid` does this is very simple. When a request enters the system, for each route configuration declaration present in the system, :app:`Pyramid` checks the ``PATH_INFO`` against the pattern declared. If any route matches, the route matching process stops. The :term:`request` is decorated with a special :term:`interface` which describes it as a "route request", the :term:`context` resource is generated, and the context and the resulting request are handed off to :term:`view lookup`. During view lookup, if a :term:`view callable` associated with the matched route is found, that view is called. :app:`Pyramid` checks the request's ``PATH_INFO`` against the pattern declared. This checking happens in the order that the routes were declared via :meth:`pyramid.config.Configurator.add_route`. When a route configuration is declared, it may contain :term:`route predicate` arguments. All route predicates associated with a route declaration must be ``True`` for the route configuration to be used for a given request. given request during a check. If any predicate in the set of :term:`route predicate` arguments provided to a route configuration returns ``False`` during a check, that route is skipped and route matching continues through the ordered set of routes. If any predicate in the set of :term:`route predicate` arguments provided to a route configuration returns ``False``, that route is skipped and route matching continues through the ordered set of routes. If any route matches, the route matching process stops and the :term:`view lookup` subsystem takes over to find the most reasonable view callable for the matched route. Most often, there's only one view that will match (a view configured with a ``route_name`` argument matching the matched route). To gain a better understanding of how routes and views are associated in a real application, you can use the ``paster pviews`` command, as documented in :ref:`displaying_matching_views`. If no route matches after all route patterns are exhausted, :app:`Pyramid` falls back to :term:`traversal` to do :term:`resource location` and @@ -1083,24 +1062,28 @@ object is decorated with the route-specific interface. - The fact that the request is decorated with a route-specific interface causes the view lookup machinery to always use the view callable registered using that interface by the route configuration to service requests that match the route pattern. causes the :term:`view lookup` machinery to always use the view callable registered using that interface by the route configuration to service requests that match the route pattern. In this way, we supply a shortcut to the developer. Under the hood, the :term:`resource location` and :term:`view lookup` subsystems provided by :app:`Pyramid` are still being utilized, but in a way which does not require a developer to understand either of them in detail. It also means that we can allow a developer to combine :term:`URL dispatch` and :term:`traversal` in various exceptional cases as documented in :ref:`hybrid_chapter`. As we can see from the above description, technically, URL dispatch doesn't actually map a URL pattern directly to a view callable. Instead, URL dispatch is a :term:`resource location` mechanism. A :app:`Pyramid` :term:`resource location` subsystem (i.e., :term:`URL dispatch` or :term:`traversal`) finds a :term:`resource` object that is the :term:`context` of a :term:`request`. Once the :term:`context` is determined, a separate subsystem named :term:`view lookup` is then responsible for finding and invoking a :term:`view callable` based on information available in the context and the request. When URL dispatch is used, the resource location and view lookup subsystems provided by :app:`Pyramid` are still being utilized, but in a way which does not require a developer to understand either of them in detail. To gain a better understanding of how routes and views are associated in a real application, you can use the ``paster pviews`` command, as documented in :ref:`displaying_matching_views`. If no route is matched using :term:`URL dispatch`, :app:`Pyramid` falls back to :term:`traversal` to handle the :term:`request`. References ---------- A tutorial showing how :term:`URL dispatch` can be used to create a :app:`Pyramid` application exists in :ref:`bfg_sql_wiki_tutorial`. docs/narr/viewconfig.rst
@@ -235,8 +235,10 @@ configured view. ``name`` The :term:`view name` required to match this view callable. Read :ref:`traversal_chapter` to understand the concept of a view name. The :term:`view name` required to match this view callable. A ``name`` argument is typically only used when your application uses :term:`traversal`. Read :ref:`traversal_chapter` to understand the concept of a view name. If ``name`` is not supplied, the empty string is used (implying the default view). @@ -417,8 +419,7 @@ from pyramid.view import view_config from pyramid.response import Response @view_config(name='my_view', request_method='POST', context=MyResource, permission='read') @view_config(route_name='ok', request_method='POST', permission='read') def my_view(request): return Response('OK') @@ -429,9 +430,8 @@ .. code-block:: python :linenos: config.add_view('mypackage.views.my_view', name='my_view', request_method='POST', context=MyResource, permission='read') config.add_view('mypackage.views.my_view', route_name='ok', request_method='POST', permission='read') All arguments to ``view_config`` may be omitted. For example: @@ -499,7 +499,7 @@ from pyramid.view import view_config from pyramid.response import Response @view_config(name='edit') @view_config(route_name='edit') def edit(request): return Response('edited!') @@ -514,7 +514,7 @@ from pyramid.response import Response from pyramid.view import view_config @view_config() @view_config(route_name='hello') class MyView(object): def __init__(self, request): self.request = request @@ -539,7 +539,7 @@ def __call__(self): return Response('hello') my_view = view_config()(MyView) my_view = view_config(route_name='hello')(MyView) More than one :class:`~pyramid.view.view_config` decorator can be stacked on top of any number of others. Each decorator creates a separate view @@ -551,8 +551,8 @@ from pyramid.view import view_config from pyramid.response import Response @view_config(name='edit') @view_config(name='change') @view_config(route_name='edit') @view_config(route_name='change') def edit(request): return Response('edited!') @@ -570,7 +570,7 @@ def __init__(self, request): self.request = request @view_config(name='hello') @view_config(route_name='hello') def amethod(self): return Response('hello') @@ -592,7 +592,7 @@ from pyramid.response import Response from pyramid.view import view_config @view_config(attr='amethod', name='hello') @view_config(attr='amethod', route_name='hello') class MyView(object): def __init__(self, request): self.request = request @@ -624,7 +624,7 @@ # config is assumed to be an instance of the # pyramid.config.Configurator class config.add_view(hello_world, name='hello.html') config.add_view(hello_world, route_name='hello') The first argument, ``view``, is required. It must either be a Python object which is the view itself or a :term:`dotted Python name` to such an object. @@ -635,102 +635,6 @@ When you use only :meth:`~pyramid.config.Configurator.add_view` to add view configurations, you don't need to issue a :term:`scan` in order for the view configuration to take effect. .. index:: single: resource interfaces .. _using_resource_interfaces: Using Resource Interfaces In View Configuration ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Instead of registering your views with a ``context`` that names a Python resource *class*, you can optionally register a view callable with a ``context`` which is an :term:`interface`. An interface can be attached arbitrarily to any resource object. View lookup treats context interfaces specially, and therefore the identity of a resource can be divorced from that of the class which implements it. As a result, associating a view with an interface can provide more flexibility for sharing a single view between two or more different implementations of a resource type. For example, if two resource objects of different Python class types share the same interface, you can use the same view configuration to specify both of them as a ``context``. In order to make use of interfaces in your application during view dispatch, you must create an interface and mark up your resource classes or instances with interface declarations that refer to this interface. To attach an interface to a resource *class*, you define the interface and use the :func:`zope.interface.implements` function to associate the interface with the class. .. code-block:: python :linenos: from zope.interface import Interface from zope.interface import implements class IHello(Interface): """ A marker interface """ class Hello(object): implements(IHello) To attach an interface to a resource *instance*, you define the interface and use the :func:`zope.interface.alsoProvides` function to associate the interface with the instance. This function mutates the instance in such a way that the interface is attached to it. .. code-block:: python :linenos: from zope.interface import Interface from zope.interface import alsoProvides class IHello(Interface): """ A marker interface """ class Hello(object): pass def make_hello(): hello = Hello() alsoProvides(hello, IHello) return hello Regardless of how you associate an interface, with a resource instance, or a resource class, the resulting code to associate that interface with a view callable is the same. Assuming the above code that defines an ``IHello`` interface lives in the root of your application, and its module is named "resources.py", the interface declaration below will associate the ``mypackage.views.hello_world`` view with resources that implement, or provide, this interface. .. code-block:: python :linenos: # config is an instance of pyramid.config.Configurator config.add_view('mypackage.views.hello_world', name='hello.html', context='mypackage.resources.IHello') Any time a resource that is determined to be the :term:`context` provides this interface, and a view named ``hello.html`` is looked up against it as per the URL, the ``mypackage.views.hello_world`` view callable will be invoked. Note, in cases where a view is registered against a resource class, and a view is also registered against an interface that the resource class implements, an ambiguity arises. Views registered for the resource class take precedence over any views registered for any interface the resource class implements. Thus, if one view configuration names a ``context`` of both the class type of a resource, and another view configuration names a ``context`` of interface implemented by the resource's class, and both view configurations are otherwise identical, the view registered for the context's class will "win". For more information about defining resources with interfaces for use within view configuration, see :ref:`resources_which_implement_interfaces`. .. index:: single: view security @@ -753,8 +657,9 @@ # config is an instance of pyramid.config.Configurator config.add_view('myproject.views.add_entry', name='add.html', context='myproject.resources.IBlog', permission='add') config.add_route('add', '/add.html', factory='mypackage.Blog') config.add_view('myproject.views.add_entry', route_name='add', permission='add') When an :term:`authorization policy` is enabled, this view will be protected with the ``add`` permission. The view will *not be called* if the user does @@ -835,7 +740,7 @@ .. index:: pair: view configuration; debugging ebugging View Configuration Debugging View Configuration ---------------------------- See :ref:`displaying_matching_views` for information about how to display docs/narr/views.rst
@@ -3,10 +3,10 @@ Views ===== One of the primary jobs of :app:`Pyramid` is to find and invoke a :term:`view callable` when a :term:`request` reaches your application. View callables are bits of code which do something interesting in response to a request made to your application. One of the primary jobs of :app:`Pyramid` is to find and invoke a :term:`view callable` when a :term:`request` reaches your application. View callables are bits of code which do something interesting in response to a request made to your application. They are the "meat" of any interesting web application. .. note:: @@ -17,23 +17,10 @@ that implements a view *callable*, and the process of view *lookup*. The :ref:`urldispatch_chapter`, and :ref:`traversal_chapter` chapters describes how, using information from the :term:`request`, a :term:`context` resource is computed. But the context resource itself isn't very useful without an associated :term:`view callable`. A view callable returns a response to a user, often using the context resource to do so. The job of actually locating and invoking the "best" :term:`view callable` is the job of the :term:`view lookup` subsystem. The view lookup subsystem compares the resource supplied by :term:`resource location` and information in the :term:`request` against :term:`view configuration` statements made by the developer to choose the most appropriate view callable for a specific set of circumstances. This chapter describes how view callables work. In the :ref:`view_config_chapter` chapter, there are details about performing view configuration, and a detailed explanation of view lookup. This chapter describes how view callables should be defined. We'll have to wait until a following chapter (entitled :ref:`view_config_chapter`) to find out how we actually tell :app:`Pyramid` to wire up view callables to particular URL patterns and other request circumstances. .. index:: single: view callables @@ -42,26 +29,20 @@ -------------- View callables are, at the risk of sounding obvious, callable Python objects. Specifically, view callables can be functions, classes, or instances that implement an ``__call__`` method (making the instance callable). objects. Specifically, view callables can be functions, classes, or instances that implement an ``__call__`` method (making the instance callable). View callables must, at a minimum, accept a single argument named ``request``. This argument represents a :app:`Pyramid` :term:`Request` object. A request object encapsulates a WSGI environment provided to :app:`Pyramid` by the upstream :term:`WSGI` server. As you might expect, the request object contains everything your application needs to know about the specific HTTP request being made. object. A request object represents a :term:`WSGI` environment provided to :app:`Pyramid` by the upstream WSGI server. As you might expect, the request object contains everything your application needs to know about the specific HTTP request being made. A view callable's ultimate responsibility is to create a :mod:`Pyramid` :term:`Response` object. This can be done by creating the response object in the view callable code and returning it directly, as we will be doing in this chapter. However, if a view callable does not return a response itself, it can be configured to use a :term:`renderer` that converts its return value into a :term:`Response` object. Using renderers is the common way that templates are used with view callables to generate markup: see the :ref:`renderers_chapter` chapter for details. In some cases, a response may also be generated by raising an exception within a view callable. :term:`Response` object. This can be done by creating a :term:`Response` object in the view callable code and returning it directly or by raising special kinds of exceptions from within the body of a view callable. .. index:: single: view calling convention @@ -160,13 +141,14 @@ object because it inherits from :class:`~pyramid.response.Response`. For examples, see :ref:`http_exceptions` and :ref:`http_redirect`. You can also return objects from view callables that aren't instances of (or instances of classes which are subclasses of) :class:`pyramid.response.Response` in various circumstances. This can be helpful when writing tests and when attempting to share code between view callables. See :ref:`renderers_chapter` for the common way to allow for this. A much less common way to allow for view callables to return non-Response objects is documented in :ref:`using_iresponse`. .. note:: You can also return objects from view callables that aren't instances of :class:`pyramid.response.Response` in various circumstances. This can be helpful when writing tests and when attempting to share code between view callables. See :ref:`renderers_chapter` for the common way to allow for this. A much less common way to allow for view callables to return non-Response objects is documented in :ref:`using_iresponse`. .. index:: single: view exceptions