.. _errors: Custom Error Documents ====================== In this article we will configure a Pecan application to display a custom error page whenever the server returns a ``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`` 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 ``HTTP 404 Page Not Found`` messages to a custom controller. First, let's update ``test_project/config.py`` to specify a new error-handler. :: # 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' key to direct HTTP status codes to a custom # controller 'errors' : { #404 : '/error/404', 404 : '/notfound', '__force_dict__' : True } } Instead of the default error page, Pecan will now route 404 messages to the controller method ``notfound``. .. _controllers: Write Custom Controllers ------------------------ The easiest way to implement the error handler is to add it to :class:`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('https://pecan.readthedocs.io/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 :class:`RootController` was:: ## 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 :func:`~pecan.decorators.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 Pecan controller, 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 of ``test_project`` as pretty or fancy as we want.