The default view is the view that gets triggered if there is no
special path segment in the URL that indicates a specific view. The
default view has as its name the empty string "", so this
registration is the equivalent of the one above:

A Collection represents a collection of objects, which can be
ordered somehow. We restrict the objects we actually get by offset and
limit. With offset 100 and limit 10, we get objects 100 through 109.

Collection is a base class, so we don’t actually implement how to
do a query. That’s up to the subclasses. We do specify that query is
supposed to return objects that have an id attribute.

We can create a view to this abstract collection that displays the
ids of the things in it in a comma separated list:

The @App.path and @App.view decorators are associated by
indirectly their model parameters: the view works for a given
model path if the model parameter is the same, or if the view is
associated with a base class of the model exposed by the
@App.path decorator.

By default @App.view returns either a morepath.Response
object or a string that gets turned into a response. The
content-type of the response is not set. For a HTML response you
want a view that sets the content-type to text/html. You can
do this by passing a render parameter to the @App.view decorator:

Sometimes you want to do things to the response specific to the view,
so that you cannot do it in a render function. Let’s say you want
to add a cookie using webob.Response.set_cookie(). You don’t
have access to the response object in the view, as it has not been
created yet. It is only created after the view has returned. We can
register a callback function to be called after the view is done and
the response is ready using the morepath.Request.after()
decorator. Here’s how:

after only applies if the view was successfully resolved into a
response. If your view raises an exception for any reason, or if
Morepath itself does, any after set in the view does not apply to
the response for this exception. If the view returns a response
object directly itself, then after is also not run - you have the
response object to manipulate directly. Note that this the case when
you use morepath.redirect(): this returns a redirect response
object.

By default, a view only answers to a GET request: it doesn’t
handle other request methods like POST or PUT or DELETE. To
write a view that handles another request method you need to be explicit and
pass in the request_method parameter:

Now we have a view that handles POST. Normally you cannot have
multiple views for the same document with the same name: the Morepath
configuration engine rejects that. But you can if you make sure they
each have a different request method:

This is equivalent to the above, you just don’t have to repeat
model=Document. You can use this for any parameter for
@App.view.

This use of the with statement is in fact general; it can be used
like this with any Morepath directive, and with any parameter for such
a directive. The with statement may even be nested, though we
recommend being careful with that, as it introduces a lot of
indentation.

We can use any information in the request and model to construct the
predicate. Now you can use it to make a view that only kicks in when
the Something` header is special:

@App.view(model=Document,something='special')defdocument_default(self,request):return"Only if request header Something is set to special."

If you have a predicate and you don’t use it in a @App.view, or
set it to None, the view works for the default value for that
predicate. The default parameter is also used when rendering a
view using morepath.Request.view() and you don’t pass in a
particular value for that predicate.

Let’s look into the predicate directive in a bit more detail.

You can use either self or request as the argument for the
predicate function. Morepath sees this argument and sends in either
the object instance or the request.

We use reg.KeyIndex as the index for this predicate. You can also
have predicate functions that return a Python class. In that case you
should use reg.ClassIndex.

morepath.LAST_VIEW_PREDICATE is the last predicate defined by Morepath
itself. Here we want to insert the something_predicate after this
predicate in the predicate evaluation order.

The after parameter for the predicate determines which predicates
match more strongly than another; a predicate after another one
matches more weakly. If there are two view candidates that both match
the predicates, the strongest match is picked.

It is often useful to be able to compose a view from other
views. Let’s look at our earlier Collection example again. What if
we wanted a generic view for our collection that included the views
for its content? This is easiest demonstrated using a JSON view:

Here we have a view that for all items returned by query includes its
view in the resulting list. Since this view is generic, we cannot
refer to a specific view function here; we just want to use the
view function appropriate to whatever item may be. For this
we can use morepath.Request.view().

where the name is some string like alpha or beta, then the
output of collection_default is something like:

['alpha','beta']

So request.view can make it much easier to construct composed JSON
results where JSON representations are only loosely coupled.

You can also use predicates in request.view. Here we get the
view with the name"edit" and the request_method"POST":

request.view(item,name="edit",request_method="POST")

You can also create views that are for internal use only. You can use
them with request.view() but they won’t show up to the web; going
to such a view is a 404 error. You can do this by passing the internal
flag to the directive:

Sometimes your application raises an exception. This can either be a
HTTP exception, for instance when the user goes to a URL that does not
exist, or an arbitrary exception raised by the application.

HTTP exceptions are by default rendered in the standard WebOb way,
which includes some text to describe Not Found, etc. Other exceptions
are normally caught by the web server and result in a HTTP 500 error
(internal server error).

You may instead want to customize what these exceptions look like. You
can do so by declaring a view using the exception class as the
model. Here’s how you make a custom 404 Not Found:

We have to add the set_status_code to make sure the response is
still a 404; otherwise we change the 404 to a 200 Ok! This shows that
self is indeed an instance of HTTPNotFound and we can access
its code attribute.

Your application may also define its own custom exceptions that have
a meaning particular to the application. You can create custom views for
those as well: