Evaluating current_user
always returns a NoneType
unless it is within a Flask application context. Do something like the following:
def get_user_roles():
_roles = []
if current_user and current_user.is_authenticated:
if current_user.role == 'a':
_roles = [('a', 'Admin'), ('m', 'Manager'), ('u', 'User')]
elif login.current_user.role == 'm':
_roles = [('m', 'Manager'), ('u', 'User')]
return _roles
class UserView(ModelView):
form_choices = {
'role' : get_user_roles
}
Single file example. If you run this without logging in you will see only the "User" role in the role choices:
requirements.txt
Babel==2.11.0
blinker==1.5
click==8.1.3
colorama==0.4.6
dnspython==2.2.1
email-validator==1.3.0
Flask==2.2.2
Flask-Admin==1.6.0
Flask-BabelEx==0.9.4
Flask-Login==0.6.2
Flask-Mail==0.9.1
Flask-Principal==0.4.0
Flask-SQLAlchemy==3.0.2
Flask-WTF==1.0.1
greenlet==2.0.1
idna==3.4
itsdangerous==2.1.2
Jinja2==3.1.2
MarkupSafe==2.1.1
passlib==1.7.4
pytz==2022.6
speaklater==1.3
SQLAlchemy==1.4.44
Werkzeug==2.2.2
WTForms==3.0.1
app.py
import os
from datetime import datetime
from werkzeug.security import generate_password_hash, check_password_hash
import click
from flask import Flask, current_app
from flask_admin import Admin
from flask_admin.contrib.sqla import ModelView
from flask_login import current_user, UserMixin, LoginManager
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
login_manager = LoginManager()
class User(db.Model, UserMixin):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
first_name = db.Column(db.Unicode(length=255), nullable=False)
last_name = db.Column(db.Unicode(length=255), nullable=False, index=True)
# Identification Data: email & password
email = db.Column(db.Unicode(length=254), nullable=False, unique=True)
password = db.Column(db.Unicode(length=255), nullable=False)
active = db.Column(db.Boolean(), default=False)
role = db.Column(db.Unicode(length=255), nullable=False)
@login_manager.user_loader
def load_user(user_id):
return User.get(user_id)
basedir = os.path.abspath(os.path.dirname(__file__))
app = Flask(__name__)
app.config['SECRET_KEY'] = '123456790'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'database.db')
db.init_app(app)
login_manager.init_app(app)
@app.cli.command('create-database', short_help='Create sample database')
def create_database():
"""
Create database
"""
db.drop_all()
db.create_all()
users = [
{
'email': 'paul@example.net',
'first_name': 'Paul',
'last_name': 'Cunningham',
'password': generate_password_hash('pa$$word'),
'active': True,
'role': 'a',
},
{
'email': 'jane@example.net',
'first_name': 'Jane',
'last_name': 'Smith',
'password': generate_password_hash('pa$$word'),
'active': True,
'role': 'm'
},
]
for user in users:
_user_db = User(**user)
db.session.add(_user_db)
db.session.commit()
@app.route('/')
def index(): # put application's code here
return '<a href="/admin/">Click me to get to Admin!</a>'
admin = Admin(app, template_mode="bootstrap3")
def get_user_roles():
# default role is a user
_roles = [('u', 'User')]
if current_user and current_user.is_authenticated:
if current_user.has_role('a'):
print('Current user is an admin')
_roles = [('a', 'Admin'), ('m', 'Manager'), ('u', 'User')]
elif current_user.has_role('m'):
print('Current user is a manager')
_roles = [('m', 'Manager'), ('u', 'User')]
print(f"Roles assigned to role choices: {_roles}")
return _roles
class UserView(ModelView):
column_list = ('first_name', 'last_name', 'email', 'role')
form_columns = column_list
form_choices = {
'role': get_user_roles
}
admin.add_view(UserView(User, db.session))
if __name__ == '__main__':
app.run()
Run the following command to initialize an SQLite DB.
flask create-database