Search code examples
pythoncherrypymako

404 error handling with mako template


Trying to display template rendered by mako on 404 errors, but it still displays standart error page with cherrypy footer and additional message: |In addition, the custom error page failed: TypeError: render_body() takes exactly 1 argument (3 given)" The code:

def error_page_404(status, message, traceback, version):
    tmpl = tpl.get_template("404.mako")
    return tmpl.render(status, message)
cherrypy.config.update({'error_page.404': error_page_404})

Need help! How to display completely custom error pages with my layout(mako template)?

Full code:

import sys
sys.stdout = sys.stderr
import os, atexit
import threading
import cherrypy
from mako.template import Template
from mako.lookup import TemplateLookup

cherrypy.config.update({'environment': 'embedded'})
if cherrypy.engine.state == 0:
    cherrypy.engine.start(blocking=False)
    atexit.register(cherrypy.engine.stop)

localDir = os.path.dirname(__file__)
absDir = os.path.join(os.getcwd(), localDir)
path = os.path.join(absDir,'files')
templ_path = os.path.join(absDir,'html')

tpl = TemplateLookup(directories=[templ_path], input_encoding='utf-8', output_encoding='utf-8',encoding_errors='replace')

def error_page_404(status, message, traceback, version):
    tmpl = tpl.get_template("404.mako")
    return tmpl.render(status, message)
cherrypy.config.update({'error_page.404': error_page_404})

class Root:
    def index(self):
    tmpl = tpl.get_template("index.mako")       
    return tmpl.render(text = 'Some text',url = cherrypy.url())
index.exposed = True    

_application = cherrypy.Application(Root(), None)

import posixpath

def application(environ, start_response):
    environ['SCRIPT_NAME'] = posixpath.dirname(environ['SCRIPT_NAME'])
    if environ['SCRIPT_NAME'] == '/':
        environ['SCRIPT_NAME'] = ''
        return _application(environ, start_response)

Solution

  • You are most likely raising an error with in your 404 handler and I guess you not setting the request.error_response of the cherrypy config like this, and about the error of response_body check this, you are probably using wrong the body of the template.

    Edit from the comments:

    def error_page_404(status, message, traceback, version):
        tmpl = tpl.get_template("404.mako")
        return tmpl.render(stat=status, msg=message)
    
    cherrypy.config.update({'error_page.404': error_page_404})
    

    The render method, only specify the function behavior with the keyword arguments, you could also be a little more flexible and specify the same function like this:

    def error_page_404(status, message, traceback, version):
        tmpl = tpl.get_template("404.mako")
        args = {'stat': status,
                'msg': message}
        return tmpl.render(**args)
    

    It will make it easier to expand your arguments for the template, I usually use **args for my render calls.

    But the basically the problem was (as you pointed out), that you where calling render with non-keyword arguments, and the expected input is just keyword arguments, for the template.