Custom Errors Documentation

- DocString'ed pecan.middleware.errordocument.py
 - Wrote a Custom Errors Cookbook
 - Fixed a bug in base config.py scaffold
This commit is contained in:
Pete
2012-03-28 18:13:27 -07:00
parent a7d4684ac5
commit 00360001b1
3 changed files with 122 additions and 4 deletions

View File

@@ -2,4 +2,115 @@
Custom Error Documents
======================
TODO
In this article we will configure a Pecan application to display a custom
Error page whenever the server returns ``404 Page not Found`` status.
This article assumes that you have already created a test application as
described in :ref:`quick_start`
.. note::
While this example focuses on the ``HTTP 404 status`` message, the same
technique may be applied to define custom actions for any of the ``HTTP``
status response codes in the 400 and 500 range. You are well advised to use
this power judiciously.
.. _overview:
Overview
--------
Pecan makes it simple to customize error documents in two simple steps:
* :ref:`configure` of the HTTP status messages you want to handle
in your application's config.py
* :ref:`controllers` to handle the status messages you have configured
.. _configure:
Configure Routing
-----------------
Let's configure our application *test_project* to route the ``HTTP 404``
(page not found) messages to our custom built controller.
First, we tweak test_project/config.py::
# Pecan Application Configurations
app = {
'root' : 'test_project.controllers.root.RootController',
'modules' : ['test_project'],
'static_root' : '%(confdir)s/public',
'template_path' : '%(confdir)s/test_project/templates',
'reload' : True,
'debug' : True,
## modify the 'errors' element to direct HTTP status codes to your
## own controller.
'errors' : {
#404 : '/error/404',
404 : '/notfound',
'__force_dict__' : True
}
}
Instead of the default error page, Pecan will now route 404 messages to our
very own controller named *notfound*.
Let us now implement the *notfound* Controller
.. _controllers:
Write Custom Controllers
------------------------
The easiest way to implement our custom *notfound* error controller is to
add it to ``test_project.root.RootController`` class
(typically in test_project/controllers/root.py)::
from pecan import expose
from webob.exc import status_map
class RootController(object):
@expose(generic=True, template='index.html')
def index(self):
return dict()
@index.when(method='POST')
def index_post(self, q):
redirect('http://pecan.readthedocs.org/en/latest/search.html?q=%s' % q)
## custom handling of '404 Page Not Found' messages
@expose('error.html')
def notfound(self):
return dict(status=404, message="test_project does not have this page")
@expose('error.html')
def error(self, status):
try:
status = int(status)
except ValueError:
status = 0
message = getattr(status_map.get(status), 'explanation', '')
return dict(status=status, message=message)
And that's it!
Notice that the only bit of code we added to our RootController is::
## custom handling of '404 Page Not Found' messages
@expose('error.html')
def notfound(self):
return dict(status=404, message="test_project does not have this page")
We simply ``@expose`` the ``notfound`` controller with the ``error.html``
template (which was conveniently generated for us and placed under
test_project/templates/ when we created ``test_project``). As with any common
controller *@expose*'d through a template, we return a dictionary of variables
for interpolation by the template renderer.
Now we can modify the error template, or write a brand new one to make the 404
error status page or ``test_project`` as pretty or fancy as we want.

View File

@@ -36,7 +36,11 @@ class StatusPersist(object):
class ErrorDocumentMiddleware(object):
'''
Intersects HTTP response status code, looks it up in the error map defined
in the Pecan app config.py, and routes to the controller assigned to that
status.
'''
def __init__(self, app, error_map):
self.app = app
self.error_map = error_map
@@ -44,6 +48,10 @@ class ErrorDocumentMiddleware(object):
def __call__(self, environ, start_response):
def replacement_start_response(status, headers, exc_info=None):
'''
Overrides the default response if the status is defined in the
Pecan app error map configuration.
'''
try:
status_code = int(status.split(' ')[0])
except (ValueError, TypeError): # pragma: nocover
@@ -60,7 +68,6 @@ class ErrorDocumentMiddleware(object):
self.error_map[status_code]
)
raise ForwardRequestException(factory=factory)
return start_response(status, headers, exc_info)
app_iter = self.app(environ, replacement_start_response)

View File

@@ -12,7 +12,7 @@ app = {
'template_path': '%(confdir)s/${package}/templates',
'debug': True,
'errors': {
'404': '/error/404',
404: '/error/404',
'__force_dict__': True
}
}