Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use g.user global in flask

As I understand the g variable in Flask, it should provide me with a global place to stash data like holding the current user after login. Is this correct?

I would like my navigation to display my user's name, once logged in, across the site.

My views contain

from Flask import g #among other things 

During login, I assign

user = User.query.filter_by(username = form.username.data).first() if validate(user):     session['logged_in'] = True     g.user = user 

It doesn't seem I can access g.user. Instead, when my base.html template has the following...

<ul class="nav">     {% if session['logged_in'] %}         <li class="inactive">logged in as {{ g.user.username }}</li>     {% endif %} </ul> 

I get the error:

jinja2.exceptions.UndefinedError UndefinedError: 'flask.ctx._RequestGlobals object' has no attribute 'user' 

The login otherwise works fine. What am I missing?

like image 845
Mittenchops Avatar asked Nov 29 '12 01:11

Mittenchops


People also ask

How do you use the G object in Flask?

g is an object for storing data during the application context of a running Flask web app. g can also be imported directly from the flask module instead of flask. globals , so you will often see that shortcut in example code.

Is Flask session global?

session is function in the Flask flask. globals module and is an instance of LocalProxy from the Werkzeug library. session stores data about the user session for the current request and it can be used to access session data.

Are global variables thread safe in Flask?

Global variables are still not thread safe because there's still no protection against most race conditions. You can still have a scenario where one worker gets a value, yields, another modifies it, yields, then the first worker also modifies it.


2 Answers

g is a thread local and is per-request (See A Note On Proxies). The session is also a thread local, but in the default context is persisted to a MAC-signed cookie and sent to the client.

The problem that you are running into is that session is rebuilt on each request (since it is sent to the client and the client sends it back to us), while data set on g is only available for the lifetime of this request.

The simplest thing to do (note simple != secure - if you need secure take a look at Flask-Login) is to simply add the user's ID to the session and load the user on each request:

@app.before_request def load_user():     if session["user_id"]:         user = User.query.filter_by(username=session["user_id"]).first()     else:         user = {"name": "Guest"}  # Make it better, use an anonymous User instead      g.user = user 
like image 75
Sean Vieira Avatar answered Sep 20 '22 04:09

Sean Vieira


Minor correction, the g object is bound to the application context now instead of the request context.

"Starting with Flask 0.10 this is stored on the application context and no longer on the request context which means it becomes available if only the application context is bound and not yet a request."

like image 26
AlexLordThorsen Avatar answered Sep 19 '22 04:09

AlexLordThorsen