kbdev
kbdev

Reputation: 1315

Flask 404 Page Not Rendering Template

I'm trying to figure out why my 404 page template will not render correctly. I am able to get it to return text, but not a template. Here is my error handler function that doesn't work:

@app.errorhandler(404)
def page_not_found(error):
    return render_template('error.html'), 404

It works if I do something like this instead:

@app.errorhandler(404)
def page_not_found(error):
    return '<h2>Page Not Found.</h2><a href="/">Click here</a> to return home.', 404

I'm using a blueprint to route the rest of my URLs. Here is more of my urls.py:

main = Blueprint('main', __name__, url_prefix='/language/<lang_code>/')
app.config.from_object(__name__)
babel = Babel(app)

def render(template_name, data):
    template_data = {
    }
    template_data.update(data)
    return render_template(template_name, **template_data)

@app.url_defaults
def set_language_code(endpoint, values):
    if 'lang_code' in values or not session['lang_code']:
        return
    if app.url_map.is_endpoint_expecting(endpoint, 'lang_code'):
        values['lang_code'] = session['lang_code']

@app.url_value_preprocessor
def get_lang_code(endpoint, values):
    if values is not None:
        session['lang_code'] = values.pop('lang_code', None)

@app.before_request
def ensure_lang_support():
    lang_code = session['lang_code']
    if lang_code and lang_code not in app.config['SUPPORTED_LANGUAGES'].keys():
        return abort(404)

@babel.localeselector
def get_locale():
    if session.get('lang_code') is None:
        session['lang_code']=request.accept_languages.best_match(app.config['SUPPORTED_LANGUAGES'].keys())
    return session['lang_code']

@app.route('/')
def root():
    return redirect(url_for('main.index_en', lang_code='en'))

@main.route('accueil', endpoint="index_fr")
@main.route('home', endpoint="index_en")
def index():
    return render('index.html', {})

app.register_blueprint(main)

Here is the error that I'm getting:

File "lib/python2.7/site-packages/flask/helpers.py", line 296, in url_for appctx.app.inject_url_defaults(endpoint, values)
File "lib/python2.7/site-packages/flask/app.py", line 1623, in inject_url_defaults func(endpoint, values)
File "app/urls.py", line 35, in set_language_code if app.url_map.is_endpoint_expecting(endpoint, 'lang_code'):
File "lib/python2.7/site-packages/werkzeug/routing.py", line 1173, in is_endpoint_expecting for rule in self._rules_by_endpoint[endpoint]:
KeyError: u'None'

Any idea why this may be happening?

Upvotes: 1

Views: 1152

Answers (1)

kbdev
kbdev

Reputation: 1315

I figured it out! The problem was not with the way I had routed my URLs, but how the language toggle was working on my site.

I had been using this:

{% if session['lang_code']=='en' %}
  {% set new_lang_code='fr' %}
{% else %}
  {% set new_lang_code='en' %}
{% endif %}
<li><a href="{{ url_for(request.endpoint|replace("_"+session['lang_code'], "_"+new_lang_code))|replace("/"+session['lang_code']+"/", "/"+new_lang_code+"/") }}">{{ _('Fr') }}</a></li>

Because the errorhandler function didn't have an endpoint, it was throwing an error. I was able to get it working by adding an if statement around the toggle like so:

{% if request.endpoint != None %}
  <li><a href="{{ url_for(request.endpoint|replace("_"+session['lang_code'], "_"+new_lang_code))|replace("/"+session['lang_code']+"/", "/"+new_lang_code+"/") }}">{{ _('Fr') }}</a></li>
{% endif %}

Upvotes: 2

Related Questions