Create a Custom 404 page

2,654 views
Skip to first unread message

Jens Hellmeier

unread,
May 7, 2010, 3:03:09 PM5/7/10
to Tornado Web Server
Hi,
How can i Create a Custom 404 page with a template file in Tornado ?

Otávio Souza

unread,
May 7, 2010, 4:40:20 PM5/7/10
to python-...@googlegroups.com
Sure.

get_error_html
"""Override to implement custom error pages.

If this error was caused by an uncaught exception, the
exception object can be found in kwargs e.g. kwargs['exception']
"""



2010/5/7 Jens Hellmeier <jens.he...@t-online.de>

Hi,
How can i Create a Custom 404 page with a template file in Tornado ?



--
Otávio Souza
* KinuX Linux Creator <http://kinuxlinux.org>
* Participante Linux-SE
* Criador dos lunatiKos (Grupo de usuários KDE do Nordeste)
* Linux User #415774

Matthew Ferguson

unread,
May 7, 2010, 4:42:29 PM5/7/10
to python-...@googlegroups.com
AFAIK that only is an error page for 500 errors, and will not be brought up in case of a 404.

There is really no perfect out-of-the-box solution, but see: http://github.com/facebook/tornado/issues/closed/#issue/71

Elias Torres

unread,
May 7, 2010, 9:35:39 PM5/7/10
to python-...@googlegroups.com, python-...@googlegroups.com
It works if you have a catch all handler and raise an HttpError(404).

-Elias

Sent from my iPhone

Ben Darnell

unread,
May 7, 2010, 9:41:33 PM5/7/10
to python-...@googlegroups.com
For a custom handler you don't even need to raise HttpError. Just
make a catch-all handler that says self.set_status(404) and then write
your output as usual.

-Ben

David P. Novakovic

unread,
May 7, 2010, 9:44:44 PM5/7/10
to python-tornado
I can't recall which error it was (probably 404), but it wasn't being
handled by that method. So i had to load my own subclasses of a
couples of classes in. I've included them below:

The important bits to know are that we subclassed built in tornado
subclasses, and overrode methods like get_error_html on the
ErrorHandler, then monkey patched that into the application.

from tornado.web import Application as _Application, RedirectHandler,\
ErrorHandler as _ErrorHandler, RequestHandler, HTTPError

class ErrorHandler(_ErrorHandler):
"""Generates an error response with status_code for all requests."""
def __init__(self, application, request, status_code):
RequestHandler.__init__(self, application, request)
self.set_status(status_code)

def prepare(self):
raise HTTPError(self._status_code)

def get_error_html(self, status_code, **kwargs):
return open(os.path.join(settings.static_path,'error','404.html')).read()


class Application(_Application):
def __call__(self, request):
"""Called by HTTPServer to execute the request."""
transforms = [t(request) for t in self.transforms]
handler = None
args = []
kwargs = {}
handlers = self._get_host_handlers(request)
if not handlers:
handler = RedirectHandler(
request, "http://" + self.default_host + "/")
else:
for spec in handlers:
match = spec.regex.match(request.path)
if match:
handler = spec.handler_class(self, request, **spec.kwargs)
# Pass matched groups to the handler. Since
# match.groups() includes both named and unnamed groups,
# we want to use either groups or groupdict but not both.
kwargs = match.groupdict()
if kwargs:
args = []
else:
args = match.groups()
break
if not handler:
handler = ErrorHandler(self, request, 404)

# In debug mode, re-compile templates and reload static files on every
# request so you don't need to restart to see changes
if self.settings.get("debug"):
if getattr(RequestHandler, "_templates", None):
map(lambda loader: loader.reset(),
RequestHandler._templates.values())
RequestHandler._static_hashes = {}

handler._execute(transforms, *args, **kwargs)
return handler


application = Application(urlpatterns, **app_conf)

David P. Novakovic

unread,
May 7, 2010, 9:45:24 PM5/7/10
to python-tornado
Eh, didn't paste properly... let me know if you want to see the proper
formatted source code.

Elias Torres

unread,
May 7, 2010, 9:46:23 PM5/7/10
to python-...@googlegroups.com, python-...@googlegroups.com
Sure. But I return 404s everywhere I can't find the resource not just
in the catch all handler. In fact I custom rendered different errors
like 403s.

-Elias

Sent from my iPhone

Jehiah

unread,
May 12, 2010, 1:41:47 AM5/12/10
to Tornado Web Server
I think what David is trying to say is that there is a different code
path for handling HTTPError's raised from a handler, compared with
handling 404 HTTPError's that are a result of no matching url regex in
the handler list.

The former calls get_error_html on the handler where the error was
raised, and the later calls get_error_html on tornado.web.ErrorHandler

I've not written a clean way to patch this, but i just define my own
ErrorHandler and set it as tornado.web.ErrorHandler
http://gist.github.com/398252

--
Jehiah

On May 7, 9:46 pm, Elias Torres <el...@torrez.us> wrote:
> Sure. But I return 404s everywhere I can't find the resource not just  
> in the catch all handler. In fact I custom rendered different errors  
> like 403s.
>
> -Elias
>
> Sent from my iPhone
>
> On May 7, 2010, at 9:41 PM, Ben Darnell <ben.darn...@gmail.com> wrote:
>
>
>
> > For a custom handler you don't even need to raise HttpError.  Just
> > make a catch-all handler that says self.set_status(404) and then write
> > your output as usual.
>
> > -Ben
>
> > On Fri, May 7, 2010 at 6:35 PM, Elias Torres <el...@torrez.us> wrote:
> >> It works if you have a catch all handler and raise an HttpError(404).
>
> >> -Elias
> >> Sent from my iPhone
> >> On May 7, 2010, at 4:42 PM, Matthew Ferguson <mbf...@gmail.com>  
> >> wrote:
>
> >> AFAIK that only is an error page for 500 errors, and will not be  
> >> brought up
> >> in case of a 404.
> >> There is really no perfect out-of-the-box solution, but
> >> see:http://github.com/facebook/tornado/issues/closed/#issue/71
> >> On May 7, 2010, at 1:40 PM, Otávio Souza wrote:
>
> >> Sure.
>
> >> get_error_html
>
> >> """Override to implement custom error pages.
> >> If this error was caused by an uncaught exception, the
> >> exception object can be found in kwargs e.g. kwargs['exception']
> >> """
>
> >> 2010/5/7 Jens Hellmeier <jens.hellme...@t-online.de>

David P. Novakovic

unread,
May 12, 2010, 1:44:12 AM5/12/10
to python-...@googlegroups.com
That would have been an easier way to do what I did :P
Reply all
Reply to author
Forward
0 new messages