Vinay Joseph
Vinay Joseph

Reputation: 5655

Setting Jinja environment global variable outside of request context

I have a function called generate_csrf_token which is located in package commons.formsecurity containing the following code.

import random
import string
from flask import session


def generate_csrf_token():
    if '_csrf_token' not in session:
        state = ''.join(random.choice(string.ascii_uppercase + string.digits)
                        for x in xrange(32))
        session['_csrf_token'] = state
    return session['_csrf_token']

I am calling this in my create_app function.

from flask import Flask
from routes_manager import configure_blueprints
from error_handling import configure_error_handling
from flask import session
from flask.ext.session import Session
from commons.formsecurity import generate_csrf_token

def create_app():
    """Create the Flask App"""
    app = Flask(__name__)
    app.secret_key = 'lalalalalala'
    app.jinja_env.globals['csrf_token'] = generate_csrf_token()
    configure_blueprints(app)
    configure_error_handling(app)
    return app

create_app is called from main.py

from app import create_app

app = create_app()

"""Run the clients"""
if __name__ == '__main__':

    app.run(debug=True)

When I run my Flask application. I get the following error.

ERROR    2017-05-25 12:12:50,720 wsgi.py:263] 
Traceback (most recent call last):
  File "C:\Program Files (x86)\Google\google_appengine\google\appengine\runtime\wsgi.py", line 240, in Handle
    handler = _config_handle.add_wsgi_middleware(self._LoadHandler())
  File "C:\Program Files (x86)\Google\google_appengine\google\appengine\runtime\wsgi.py", line 299, in _LoadHandler
    handler, path, err = LoadObject(self._handler)
  File "C:\Program Files (x86)\Google\google_appengine\google\appengine\runtime\wsgi.py", line 85, in LoadObject
    obj = __import__(path[0])
  File "C:\Code\App-Engine\cfc-melbourne-website\main.py", line 3, in <module>
    app = create_app()
  File "C:\Code\App-Engine\cfc-melbourne-website\app\__init__.py", line 12, in create_app
    app.jinja_env.globals['csrf_token'] = generate_csrf_token()
  File "C:\Code\App-Engine\cfc-melbourne-website\app\commons\formsecurity.py", line 7, in generate_csrf_token
    if '_csrf_token' not in session:
  File "lib\werkzeug\local.py", line 379, in <lambda>
    __contains__ = lambda x, i: i in x._get_current_object()
  File "lib\werkzeug\local.py", line 306, in _get_current_object
    return self.__local()
  File "lib\flask\globals.py", line 37, in _lookup_req_object
    raise RuntimeError(_request_ctx_err_msg)
RuntimeError: Working outside of request context.

This typically means that you attempted to use functionality that needed
an active HTTP request.  Consult the documentation on testing for
information about how to avoid this problem.

Where is the best place to call the following

app.jinja_env.globals['csrf_token'] = generate_csrf_token()

Upvotes: 1

Views: 3910

Answers (1)

farzad
farzad

Reputation: 8855

If you don't call the generate_csrf_token() function, and instead store the reference to the function, you can call it in your Jinja templates (which will be in the context where a request is available).

So replace

app.jinja_env.globals['csrf_token'] = generate_csrf_token()

With

app.jinja_env.globals['csrf_token'] = generate_csrf_token

And in your templates, use:

<input name=_csrf_token type=hidden value="{{ csrf_token() }}">

Upvotes: 3

Related Questions