Search code examples
flaskflask-login

Flask Login: User.is_anonymous() is a function, but current_user.is_anonymous is an attribute. Why?


This is my first time using flask-login, and I need to support anonymous users. Authenticated users will have special privileges. My User model implements its own version of the UserMixin functions; the relevant part is:

    def is_authenticated(self):
        """Return True if the user is authenticated."""
        return self.authenticated

    def is_anonymous(self):
        """If you're not authenticated, you're anonymous."""
        return not self.authenticated

Some templates will have code like the following:

{% if current_user is not defined or current_user.is_anonymous %}
...render HTML 1
{% else %}
...render HTML 2
{% endif %}

This works fine for anonymous users, but authenticated users will also see HTML 1 because current_user.is_anonymous evaluates to <bound method User.is_anonymous of <User *email-address*>. Meanwhile, if I change the condition to current_user.is_anonymous(), that will throw an error for anonymous users ("TypeError: 'bool' object is not callable"). My understanding is that the User Model needs is_anonymous to be a function, but its a Boolean attribute of current_user. This inconsistency is kind of irritating, but I feel like I'm missing something obvious.

What is the best way to correctly check to see if a user is anonymous?

EDIT: This is my user_loader:

@login_manager.user_loader
def load_user(user_id):
    if user_id is not None:
        return User.query.filter_by(email=user_id).first()
    
    return None

EDIT 2: I removed my custom context processor bc I learned that LoginManager provides one for me. Still, the problem persists. In my templates, current_user.is_anonymous still evaluates to <bound function....


Solution

  • Victor is correct; I was missing the @property decorator. I knew it was something simple. Thanks Victor!