Skip to main content

With Flask-Login, you want current_user == None, not current_user is None

current_user is a proxy object that happens to be wrapping None, but isn’t actually None.

I was writing some code that uses Flask-Login, and I wanted to test the scenario where a user wasn’t logged in.

I get the value of current_user, and it’s None:

>>> from flask_login import current_user
>>> current_user
None

Great! So now I can check if this value is None, and react accordingly:

>>> if current_user is None:
...     print("Nobody is logged in!")
...
>>>

Hmm.

If you look at how Flask-Login works, you see that current_user is defined as a LocalProxy that wraps the _get_user() function:

from werkzeug.local import LocalProxy

...

#: A proxy for the current user. If no user is logged in, this will be an
#: anonymous user
current_user = LocalProxy(lambda: _get_user())

This LocalProxy class is some sort of wrapper. The Werkzeug docstring describes it as “a proxy to the object bound to a context-local object” which doesn’t mean much to me, but I can see that it’s getting in the way of the identity checks.

In particular, the wrapper is equal to None but not identical to it:

>>> p = LocalProxy(lambda: None)
>>> p
None
>>> p == None
True
>>> p is None
False
>>> id(p)
4349196416
>>> id(None)
4343995648

This means my code has to use current_user == None, not current_user is None. This looks odd – generally it’s better Python to use is None as a comparison, but in this case it won’t work.