How to use g.user global in flask
Solution 1
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
Solution 2
Minor correction, the g object is bound to the application context now instead of the request context.
Mittenchops
Updated on July 08, 2022Comments
-
Mittenchops almost 2 years
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?
-
Mittenchops over 11 yearsThanks, Sean, that clarifies for me what's going on with g. I don't suppose you have further comment on what is the insecure part about sessions and how to implement this better with Flask-Login? Is the solution so simple as use Flask-Login and then using the session[] variable is then secure? Would you recommend against using g at all as seen in the tutorial I linked to?
-
Sean Vieira over 11 years@Mittenchops - Flask-Login still uses
session
- it simply deals with all the corner cases of managing login / logouts, forcing re-authentication when necessary, etc. The potential of getting those corner cases wrong is what makes your application less secure.g
is safe to use regardless - it is not constructed out of user-provided data and so may be considered "safe". -
Mittenchops over 11 yearsSean, can I follow up one thing on this? Suppose I'm using the kvsession to secure my cookies (rather than simply to sign them). Is there then any benefit using g instead of session? Is there some esoteric difference in memory usage or something whether I set session["user"] or g.user?
-
Sean Vieira over 11 years@Mittenchops - as long as what you are storing is serializable
session
is probably a better bet (simply becauseg
is torn down at the end of every request whilesession
is preserved between requests). So, assuming thatUser
could be serialized you could do:if "user" not in session: # query database
and avoid numerous calls to the DB (An un-enhancedg
would require a DB call on every request since it is always built afresh). -
Emil Vatai over 9 yearsSince I'm a bit new to web development, may I check if I understand everything? I should use session['key']='value' if 'value' is a string (or something which can be stored as a string), and use g.key = value is values is a bit more 'complicated' python object (or something what is not storable as a string). And session will be stored per connection 'until the browser is closed', and g will be deleted for each request i.e. for each 'enter' pressed in the address bar.
-
FabioCosta over 8 yearsSo the g will be the same on every request on the same proccess ? So if i send a request and save something on 'g' and another request cames ths value would still be there ?
-
pors almost 8 years@FabioCosta nope, you still need the session for that
-
Antoine Lizée over 7 yearsIt seems from the code that
g
is not defined per request but per app context. That makes a hell of a difference. -
Sean Vieira over 7 years@AntoineLizée - that is correct now - at the time this answer was written though it was not (appcontext was added in the 0.10 release, which came out the month after this answer was written). I'll update.
-
Sean Vieira over 7 yearsIn either case, what is on
g
is done for each request (you can't share values across requests ong
). -
colidyre almost 7 years
Better yet: get rid of flask
-- wtf?