python - 如何将flask_login 与多个用户类和不同的数据库条目一起使用?

标签 python flask flask-sqlalchemy flask-login

如果有人拥有一个包含多种“类型”用户的 Flask Web 应用程序,例如在学校环境中,可能有“教师”、“学生”和“管理员”。每个用户都需要有一种登录应用程序的方式,但 Flask-Login 只提供了一种@login.user_loader。我的问题类似于 this question ,关于多个用户类别,但不同的是,每种类型的用户不具有与其他用户相同的模型结构。例如,如果要使用flask-sqlalchemy并声明以下模型:

class Teacher(db.Model, UserMixin):
    id = db.Column(db.Integer,primary_key=True)
    title = db.Column(db.String(32))
    pwd_hash = db.Column(db.String(128))
    first_name = db.Column(db.String(128))
    last_name = db.Column(db.String(128))
    students = db.relationship('Student',backref='teacher',lazy='dynamic') #because a teacher will teach multiple students
    
class Student(db.Model, UserMixin):
    id = db.Column(db.Integer,primary_key=True)
    username = db.Column(db.String(64),unique=True)
    teacher_id = db.Column(db.ForeignKey('teacher.id'),db.Integer) #for the ease of things, the student is only ever taught by one teacher

class Admin(db.Model, UserMixin):
    email = db.Column(db.String(128),unique=True)
    name = db.Column(db.String(128))

user_loader 通常是这样使用的,这里的 User 类是一个通用的用户类:

@login.user_loader
def load_user(id):
    return User.query.get(int(id))

这意味着您必须只有一个可以登录的 User 类。通常的方法是压缩 StudentTeacherAdmin 类合并到一个 User 类中,模型中带有一个 role 字段,该字段告诉您它们的访问级别。但这会带来多个问题。例如,并非所有学生都有可用的电子邮件,但学校的管理帐户需要一个。同样,学生和教师之间的关系也会失败,因为教师没有让学生加入类(class)的模式等。

那么我如何实现一种方法,让多个用户模型具有不同的属性和模型字段,每个模型都可以使用flask_login单独登录?

最佳答案

您的用户只需要一个ID和与该用户对应的表的关系。您可以通过为角色和角色关系创建一个表来创建它:

class User(db.Model, UserMixin):
    """"""
    __tablename__ = "user"
    # Core
    id = db.Column(db.Integer,primary_key=True)
    roles = db.relationship('Role', secondary=roles_users,
                            backref=db.backref('users', lazy='dynamic'))

class Role(db.Model, RoleMixin):
    __tablename__ = "role"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(80), unique=True)

roles_users = db.Table('roles_users',
        db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
        db.Column('role_id', db.Integer(), db.ForeignKey('role.id')))

您可以使用以下命令检查给定角色:

class User(db.Model, UserMixin):
    # all the args go here...
    ...
    def has_role(self, role_name):
        """Does this user have this permission?"""
        my_role = Role.query.filter_by(name=role_name).first()
        if my_role in self.roles:
            return True
        else:
            return False

接下来,创建一个检查角色的装饰器

from flask import redirect
from flask_login import current_user
from functools import wraps


def require_role(role):
    """make sure user has this role"""
    def decorator(func):
        @wraps(func)
        def wrapped_function(*args, **kwargs):
            if not current_user.has_role(role):
                return redirect("/")
            else:
                return func(*args, **kwargs)
        return wrapped_function
    return decorator

第3步:在操作中应用装饰器:

@app.route("/")
@login_required
@require_role(role="teacher")
def teachers():
    """Only allow teachers"""
    # Otherwise, proceed
    return render_template('teachers.html')

关于python - 如何将flask_login 与多个用户类和不同的数据库条目一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64091972/

相关文章:

python - 将日期插入数据库时​​丢失微秒

python - 最短路线优化不起作用

python - 在 Flask-SQLAlchemy 中自动格式化 db.Datetime 值

flask - 如何使用 SQLalchemy 和 Alembic 自动初始化数据库?

python - 如何在 tensorflow 数据集的每次迭代中添加随机性?

python - 获取组内的最大值,但不仅仅是第一个(ex æquo 也是如此)

javascript - 如何从 Javascript/React 发送 AJAX 请求并在 Python REST API 中接收数据

python - 找不到 flask 、Nginx、uWSGI Python 应用程序

python - 尝试在 Nginx 服务器 Ubuntu 21.10 实例上部署我的 flask 应用程序时,我得到了经典的 "Permission denied while connecting to upstream"

sqlalchemy - 如何连接到嵌入 SQLAlchemy 的 Firebird