diff options
| author | Chris McDonough <chrism@agendaless.com> | 2009-11-28 01:54:50 +0000 |
|---|---|---|
| committer | Chris McDonough <chrism@agendaless.com> | 2009-11-28 01:54:50 +0000 |
| commit | 6103bf8050466329aba930df000f042dbdff8efa (patch) | |
| tree | 1dd16982214ff634d7c46082eb86468bf24a73b9 /docs | |
| parent | 0970432b72d8f4360b69dc58223ea0725d747d36 (diff) | |
| download | pyramid-6103bf8050466329aba930df000f042dbdff8efa.tar.gz pyramid-6103bf8050466329aba930df000f042dbdff8efa.tar.bz2 pyramid-6103bf8050466329aba930df000f042dbdff8efa.zip | |
Document the request-only calling convention as the default.
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/narr/MyProject/myproject/tests.py | 3 | ||||
| -rw-r--r-- | docs/narr/MyProject/myproject/views.py | 2 | ||||
| -rw-r--r-- | docs/narr/hooks.rst | 4 | ||||
| -rw-r--r-- | docs/narr/security.rst | 2 | ||||
| -rw-r--r-- | docs/narr/templates.rst | 14 | ||||
| -rw-r--r-- | docs/narr/unittesting.rst | 18 | ||||
| -rw-r--r-- | docs/narr/views.rst | 165 |
7 files changed, 101 insertions, 107 deletions
diff --git a/docs/narr/MyProject/myproject/tests.py b/docs/narr/MyProject/myproject/tests.py index 8b3fcc73b..7c3caac74 100644 --- a/docs/narr/MyProject/myproject/tests.py +++ b/docs/narr/MyProject/myproject/tests.py @@ -11,8 +11,7 @@ class ViewTests(unittest.TestCase): def test_my_view(self): from myproject.views import my_view - context = testing.DummyModel() request = testing.DummyRequest() - info = my_view(context, request) + info = my_view(request) self.assertEqual(info['project'], 'MyProject') diff --git a/docs/narr/MyProject/myproject/views.py b/docs/narr/MyProject/myproject/views.py index 036b140fb..c43b34460 100644 --- a/docs/narr/MyProject/myproject/views.py +++ b/docs/narr/MyProject/myproject/views.py @@ -1,2 +1,2 @@ -def my_view(context, request): +def my_view(request): return {'project':'MyProject'} diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst index 8f6e0f62f..28a76c018 100644 --- a/docs/narr/hooks.rst +++ b/docs/narr/hooks.rst @@ -95,7 +95,7 @@ Here's some sample code that implements a minimal NotFound view: from webob.exc import HTTPNotFound - def notfound_view(context, request): + def notfound_view(request): return HTTPNotFound() .. note:: When a NotFound view is invoked, it is passed a request. @@ -203,7 +203,7 @@ Here's some sample code that implements a minimal forbidden view: from repoze.bfg.chameleon_zpt import render_template_to_response - def forbidden_view(context, request): + def forbidden_view(request): return render_template_to_response('templates/login_form.pt') .. note:: When an forbidden view is invoked, it is passed diff --git a/docs/narr/security.rst b/docs/narr/security.rst index acc1dff01..a733aef9b 100644 --- a/docs/narr/security.rst +++ b/docs/narr/security.rst @@ -92,7 +92,7 @@ module of your project's package from models import Blog @bfg_view(for_=Blog, name='add_entry.html', permission='add') - def blog_entry_add_view(context, request): + def blog_entry_add_view(request): """ Add blog entry code goes here """ pass diff --git a/docs/narr/templates.rst b/docs/narr/templates.rst index e7c20795e..a94c493a6 100644 --- a/docs/narr/templates.rst +++ b/docs/narr/templates.rst @@ -35,7 +35,7 @@ the template from a view like so: :linenos: from repoze.bfg.chameleon_zpt import render_template_to_response - def sample_view(context, request): + def sample_view(request): return render_template_to_response('templates/foo.pt', foo=1, bar=2) The first argument to ``render_template_to_response`` shown above (and @@ -68,7 +68,7 @@ string manually as a response body. Here's an example of using from repoze.bfg.chameleon_zpt import render_template from webob import Response - def sample_view(context, request): + def sample_view(request): result = render_template('templates/foo.pt', foo=1, bar=2) response = Response(result) response.content_type = 'text/plain' @@ -81,7 +81,7 @@ changing the content-type and status: :linenos: from repoze.bfg.chameleon_zpt import render_template_to_response - def sample_view(context, request): + def sample_view(request): response = render_template_to_response('templates/foo.pt', foo=1, bar=2) response.content_type = 'text/plain' response.status_int = 204 @@ -144,7 +144,7 @@ it in to the template being rendered. For example: from repoze.bfg.chameleon_zpt import render_template_to_response from repoze.bfg.chameleon_zpt import get_template - def my_view(context, request): + def my_view(request): main = get_template('templates/master.pt') return render_template_to_response('templates/mytemplate.pt', main=main) @@ -200,7 +200,7 @@ which renders this template: from repoze.bfg.chameleon_text import render_template_to_response - def text_view(context, request): + def text_view(request): return render_template_to_response('templates/text.txt', name='World') The Chameleon text rendering API is a wholesale mirror of the @@ -291,9 +291,9 @@ installed, here's an example of using Mako from within a from mako.template import Template from webob import Response - def make_view(context, request): + def make_view(request): template = Template(filename='/templates/template.mak') - result = template.render(name=context.name) + result = template.render(name=request.params['name']) response = Response(result) return response diff --git a/docs/narr/unittesting.rst b/docs/narr/unittesting.rst index d31be3056..d94c94d99 100644 --- a/docs/narr/unittesting.rst +++ b/docs/narr/unittesting.rst @@ -49,7 +49,7 @@ to unit test a :mod:`repoze.bfg` view function. .. code-block:: python :linenos: - def view_fn(context, request): + def view_fn(request): from repoze.bfg.chameleon_zpt import render_template_to_response if 'say' in request.params: return render_template_to_response('templates/submitted.pt', @@ -88,18 +88,16 @@ unittest TestCase that used the testing API. def test_view_fn_not_submitted(self): from my.package import view_fn renderer = testing.registerTemplateRenderer('templates/show.pt') - context = testing.DummyModel() request = testing.DummyRequest() - response = view_fn(context, request) + response = view_fn(request) renderer.assert_(say='Hello') def test_view_fn_submitted(self): from my.package import view_fn renderer = testing.registerTemplateRenderer('templates/submitted.pt') - context = testing.DummyModel() request = testing.DummyRequest() request.params['say'] = 'Yo' - response = view_fn(context, request) + response = view_fn(request) renderer.assert_(say='Yo') In the above example, we create a ``MyTest`` test case that inherits @@ -113,10 +111,9 @@ request.params) have been submitted. Its first line registers a "dummy template renderer" named ``templates/show.pt`` via the ``registerTemplateRenderer`` function (a ``repoze.bfg.testing`` API); this function returns a DummyTemplateRenderer instance which we hang -on to for later. We then create a ``DummyRequest`` object (it -simulates a WebOb request object), and we create a ``DummyModel`` -context object. We call the function being tested with the -manufactured context and request. When the function is called, +on to for later. We then create a ``DummyRequest`` object which +simulates a WebOb request object). We call the function being tested +with the manufactured request. When the function is called, ``render_template_to_response`` will call the "dummy" template renderer object instead of the real template renderer object. When the dummy renderer is called, it will set attributes on itself @@ -199,9 +196,8 @@ environment. def test_my_view(self): from myapp.views import my_view - context = testing.DummyModel() request = testing.DummyRequest() - result = my_view(context, request) + result = my_view(request) self.assertEqual(result.status, '200 OK') body = result.app_iter[0] self.failUnless('Welcome to' in body) diff --git a/docs/narr/views.rst b/docs/narr/views.rst index 390be4c99..c7c0a640e 100644 --- a/docs/narr/views.rst +++ b/docs/narr/views.rst @@ -6,29 +6,34 @@ Views A :term:`view callable` is a callable which is invoked when a request enters your application. The primary job of any :mod:`repoze.bfg` application is is to find and call a :term:`view callable` when a -:term:`request` reaches it. A :term:`view callable` is referred to, -in shorthand, as a :term:`view`. +:term:`request` reaches it. A :term:`view callable` is referred to in +shorthand as a :term:`view`. -See :ref:`traversal_intro` for an example of how a view might be found -as the result of a request. +.. note:: See :ref:`traversal_intro` for an example of how a view + might be found as the result of a request. -A view callable may always return a :term:`WebOb` ``Response`` object -directly. It may optionally return another arbitrary non-`Response` -value. If a view callable returns a non-Response result, the result -will be converted into a response by the :term:`renderer` associated -with the :term:`view configuration` for the view. +Most views accept a single argument: ``request``. This argument +represents a WebOb Request object representing the current WSGI +request. + +A view callable may always return a :term:`WebOb` :term:`Response` +object directly. It may optionally return another arbitrary +non-Response value. If a view callable returns a non-Response result, +the result will be converted into a response by the :term:`renderer` +associated with the :term:`view configuration` for the view. A view is mapped to one or more URLs by virtue of :term:`view configuration`. View configuration is performed by using the -``add_view`` method of a :term:`Configurator` object, by adding -``<view>`` statements to :term:`ZCML` used by your application, or by -attaching ``@bfg_view`` decorators to Python objects in your -application source code. Each of these mechanisms are equivalent. +``add_view`` method of a :term:`Configurator` object, by adding a +``<view>`` statement to :term:`ZCML` used by your application, or by +running a :term:`scan` against application source code which has a +``@bfg_view`` decorator attached to a Python object. Each of these +mechanisms are equivalent. A view might also be mapped to a URL by virtue of :term:`route configuration`. Route configuration is performed by using the -``add_route`` method of a :term:`Configurator` object or by adding -``<route>`` statements to :term:`ZCML` used by your application. See +``add_route`` method of a :term:`Configurator` object or by adding a +``<route>`` statement to :term:`ZCML` used by your application. See :ref:`urldispatch_chapter` for more information on mapping URLs to views using routes. @@ -38,16 +43,16 @@ Defining a View as a Function ----------------------------- The easiest way to define a view is to create a function that accepts -two arguments: :term:`context`, and :term:`request` and which returns -a response object. For example, this is a "hello world" view -implemented as a function: +a single argument: :term:`request` and which returns a response +object. For example, this is a "hello world" view implemented as a +function: .. code-block:: python :linenos: from webob import Response - def hello_world(context, request): + def hello_world(request): return Response('Hello world!') .. _class_as_view: @@ -60,13 +65,13 @@ Defining a View as a Class A view callable may also be a class instead of a function. When a view callable is a class, the calling semantics are slightly different than when it is a function or another non-class callable. When a view -is a class, the class' ``__init__`` is called with the context and the -request parameters. As a result, an instance of the class is created. +is a class, the class' ``__init__`` is called with the request +parameter. As a result, an instance of the class is created. Subsequently, that instance's ``__call__`` method is invoked with no parameters. Views defined as classes must have the following traits: -- an ``__init__`` method that accepts a ``context`` and a ``request`` - as positional arguments. +- an ``__init__`` method that accepts a ``request`` as its sole + positional arguments. - a ``__call__`` method that accepts no parameters and returns a response. @@ -79,15 +84,14 @@ For example: from webob import Response class MyView(object): - def __init__(self, context, request): - self.context = context + def __init__(self, request): self.request = request def __call__(self): - return Response('hello from %r!' % self.context) + return Response('hello') -The context and request objects passed to ``__init__`` are the same -types of objects as described in :ref:`function_as_view`. +The request object passed to ``__init__`` is the same type of request +object described in :ref:`function_as_view`. If you'd like to use a different attribute than ``__call__`` to represent the method expected to return a response, you can use an @@ -96,61 +100,60 @@ represent the method expected to return a response, you can use an .. _request_only_view_definitions: -Request-Only View Definitions ------------------------------ +Request-And-Context View Definitions +------------------------------------ View callables may alternately be defined as classes or functions (or -any callable) that accept only a *request* object, instead of both a -context and a request. The following types work as views in this -style: +any callable) that accept two positional arguments: a :term:`context` +as the first argument and a :term:`request` as the second argument. +The :term:`context` and :term:`request` arguments passed to a view +function defined in this style can be defined as follows: + +context + + An instance of a :term:`context` found via graph :term:`traversal` + or :term:`URL dispatch`. If the context is found via traversal, it + will be a :term:`model` object. + +request + + A WebOb Request object representing the current WSGI request. + +The following types work as views in this style: -#. Functions that accept a single argument ``request``, e.g.:: +#. Functions that accept two arguments: ``context``, and ``request``, + e.g.:: from webob import Response - def view(request): + def view(context, request): return Response('OK') #. New-style and old-style classes that have an ``__init__`` method - that accepts ``self, request``, e.g.:: + that accepts ``self, context, request``, e.g.:: from webob import Response class view(object): - __init__(self, request): + __init__(self, context, request): return Response('OK') #. Arbitrary callables that have a ``__call__`` method that accepts - ``self, request``, e.g.:: + ``self, context, request``, e.g.:: from webob import Response class View(object): - def __call__(self, request): + def __call__(self, context, request): return Response('OK') view = View() # this is the view callable -This style of calling convention is useful for :term:`url dispatch` -based applications, where the context is seldom used within the view -code itself. The view always has access to the context via -``request.context`` in any case, so it's still available even if you -use the request-only calling convention. +This style of calling convention is useful for :term:`traversal` based +applications, where the context object is frequently used within the +view code itself. -Arguments Passed to a View --------------------------- - -The :term:`context` and :term:`request` arguments passed to a view -function can be defined as follows: - -context - - An instance of a :term:`context` found via graph :term:`traversal` - or :term:`URL dispatch`. If the context is found via traversal, it - will be a :term:`model` object. - -request - - A WebOb Request object representing the current WSGI request. +No matter which view calling convention is used, the view always has +access to the context via ``request.context``. .. _the_response: @@ -296,8 +299,8 @@ You can also declare a *default view* for a model type: /> A *default view* has no ``name`` attribute. When a :term:`context` is -traversed and there is no *view name* in the request, the *default -view* is the view that is used. +found and there is no *view name* associated with the result of +:term:`traversal`, the *default view* is the view that is used. You can also declare that a view is good for any model type by using the special ``*`` character in the ``for`` attribute: @@ -629,7 +632,7 @@ An example might reside in a bfg application module ``views.py``: @bfg_view(name='my_view', request_type='POST', for_=MyModel, permission='read') - def my_view(context, request): + def my_view(request): return render_template_to_response('templates/my.pt') Using this decorator as above replaces the need to add this ZCML to @@ -720,7 +723,7 @@ All arguments may be omitted. For example: from webob import Response @bfg_view() - def my_view(context, request): + def my_view(request): """ My view """ return Response() @@ -743,12 +746,11 @@ applied against a function. For example: @bfg_view() class MyView(object): - def __init__(self, context, request): - self.context = context + def __init__(self, request): self.request = request def __call__(self): - return Response('hello from %s!' % self.context) + return Response('hello') You can use the ``bfg_view`` decorator as a simple callable to manually decorate classes in Python 2.5 and below (without the @@ -761,12 +763,11 @@ decorator syntactic sugar), if you wish: from repoze.bfg.view import bfg_view class MyView(object): - def __init__(self, context, request): - self.context = context + def __init__(self, request): self.request = request def __call__(self): - return Response('hello from %s!' % self.context) + return Response('hello') my_view = bfg_view()(MyView) @@ -781,7 +782,7 @@ registration. For example: @bfg_view(name='edit') @bfg_view(name='change') - def edit(context, request): + def edit(request): pass This registers the same view under two different names. @@ -800,13 +801,12 @@ The bfg_view decorator can also be used against class methods: from repoze.bfg.view import bfg_view class MyView(object): - def __init__(self, context, request): - self.context = context + def __init__(self, request): self.request = request @bfg_view(name='hello') def amethod(self): - return Response('hello from %s!' % self.context) + return Response('hello') When the bfg_view decorator is used against a class method, a view is registered for the *class*, so the class constructor must accept @@ -825,12 +825,11 @@ could be spelled equivalently as the below: @bfg_view(attr='amethod', name='hello') class MyView(object): - def __init__(self, context, request): - self.context = context + def __init__(self, request): self.request = request def amethod(self): - return Response('hello from %s!' % self.context) + return Response('hello') .. note:: The ability to use the ``bfg_view`` decorator as a method decorator is new in :mod:`repoze.bfg` version 1.1. @@ -1019,7 +1018,7 @@ representation of the dictionary: from repoze.bfg.view import bfg_view @bfg_view(renderer='string') - def hello_world(context, request): + def hello_world(request): return {'content':'Hello!'} The body of the response returned by such a view will be a string @@ -1050,7 +1049,7 @@ view will render the returned dictionary to a JSON serialization: from repoze.bfg.view import bfg_view @bfg_view(renderer='json') - def hello_world(context, request): + def hello_world(request): return {'content':'Hello!'} The body of the response returned by such a view will be a string @@ -1208,7 +1207,7 @@ slightly different response. from webob.exc import HTTPFound - def myview(context, request): + def myview(request): return HTTPFound(location='http://example.com') All exception types from the :mod:`webob.exc` module implement the @@ -1344,7 +1343,7 @@ ZCML file: from repoze.bfg.url import static_url from repoze.bfg.chameleon_zpt import render_template_to_response - def my_view(context, request): + def my_view(request): css_url = static_url('resources/1/foo.css', request) js_url = static_url('resources/2/foo.js', request) return render_template_to_response('templates/my_template.pt', @@ -1484,7 +1483,7 @@ accept a form post from the above form: .. code-block:: python - def myview(context, request): + def myview(request): firstname = request.params['firstname'] lastname = request.params['lastname'] @@ -1494,7 +1493,7 @@ decode already-decoded (``unicode``) values obtained from .. code-block:: python - def myview(context, request): + def myview(request): # the .decode('utf-8') will break below if there are any high-order # characters in the firstname or lastname firstname = request.params['firstname'].decode('utf-8') @@ -1695,7 +1694,7 @@ attribute: from repoze.bfg.view import bfg_view @bfg_view(renderer='amf') - def myview(context, request): + def myview(request): return {'Hello':'world'} By default, when a template extension is unrecognized, an error is |
