Order of AND Operations for Jinja2?

Viewed 69

I want to authenticate if the current_user object have 'Admin' in its role set to restrict taps from appearing in Jinja2.

However, if I only used {% if 'Admin' in current_user.format()['roles'] %} most of the time it will give me error

current_user is Non-type object

So, I used the following syntax and it worked for me locally.

{% if current_user.is_authenticated and ('Admin' in current_user.format()['roles']) %}

    ...
    ...
    ...

{% endif %}

The only issue I am not sure of the order of AND operation for Jinja2 and I am afraid the second condition after the AND operator is going to run first, and this will cause me trouble if I proceed with this code in the production server.

So my question:

Is there documentation about the order of operation in Jinja2, or any other reliable reference? Or if someone know whether the sequence of operation will always start from the left or not?

The model below is the class which current_user inherits from:

class Authorization(db.Model, UserMixin):
    __tablename__ = 'authorizations'
    id = db.Column(db.Integer, primary_key=True)
    active = db.Column('is_active', db.Boolean(), nullable=False, server_default='0')

    # User authentication information. The collation='NOCASE' is required
    # to search case insensitively when USER_IFIND_MODE is 'nocase_collation'.
    username = db.Column(db.BigInteger, nullable=False, unique=True)
    password = db.Column(db.String(255), nullable=False, server_default='')
    # Define the relationship to Role via UserRoles
    roles = db.relationship('Role', secondary='user_roles')
    
    def format(self):
        roles = [role.name for role in self.roles]
        print(roles)
        return {
            'id': self.id,
            'active': self.active,
            'username': self.username,
            'roles': roles,
        }

# Define the Role data-model
class Role(db.Model):
    __tablename__ = 'roles'
    id = db.Column(db.Integer(), primary_key=True)
    name = db.Column(db.String(50), unique=True)

# Define the UserRoles association table
class UserRoles(db.Model):
    __tablename__ = 'user_roles'
    id = db.Column(db.Integer(), primary_key=True)
    user_id = db.Column(db.Integer(), db.ForeignKey('authorizations.id', ondelete='CASCADE'))
    role_id = db.Column(db.Integer(), db.ForeignKey('roles.id', ondelete='CASCADE'))
1 Answers

The concept you are referring to is known as short-circuit evaluation. In a language that supports short-circuit evalaution, if you have an expression such as condition_A and condition_B, and condition_A turns out to be false, then condition_B won't be evaluated at all, even if condition_B would raise an exception.

The Jinja2 docs don't seem to state directly whether Jinja2 supports short-circuit evaluation with and and or. The best indication I can find that it does is within the AST extension, where the And class is referred to as 'Short circuited AND'.

Short-circuit evaluation is a convention used by many languages, including Python, so I would say you would be safe to write something like

{% if condition_A and condition_B %}

if your condition_B would raise an exception if condition_A is false.

Related