flask-security add_role_to_user不接受用户名

时间:2018-04-10 14:34:50

标签: flask flask-sqlalchemy flask-security

在尝试为用户分配角色时,使用用户名而不是电子邮件的诀窍是什么?

以下作品:

user_datastore.add_role_to_user('nunya@beezwax.com', 'site-admin')

这不起作用:

user_datastore.add_role_to_user('admin', 'site-admin')

它给出的错误是:

AttributeError: 'NoneType' object has no attribute 'roles'

我的模型看起来像这样:

roles_users = db.Table('users_to_roles',
    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):
  id = db.Column(db.Integer, primary_key=True)
  username = db.Column(db.String(16), unique=True)
  email = db.Column(db.String(256), unique=True)
  password = db.Column(db.String(255))
  active = db.Column(db.Boolean())
  confirmed_at = db.Column(db.DateTime())
  roles = db.relationship('Role', secondary=roles_users,
                        backref=db.backref('users', lazy='dynamic'))

3 个答案:

答案 0 :(得分:0)

如果查看源代码,https://github.com/mattupstate/flask-security/blob/develop/flask_security/datastore.py add_role_to_user调用方法

def add_role_to_user(self, user, role):
        """Adds a role to a user.
        :param user: The user to manipulate
        :param role: The role to add to the user
        """
        user, role = self._prepare_role_modify_args(user, role)
        if role not in user.roles:
            user.roles.append(role)
            self.put(user)
            return True
        return False

反过来调用

def _prepare_role_modify_args(self, user, role):
        if isinstance(user, string_types):
            user = self.find_user(email=user)
        if isinstance(role, string_types):
            role = self.find_role(role)
        return user, role

此方法使用电子邮件检索用户对象。如果你真的需要通过用户名检索(并确保其唯一的)而不是电子邮件,你可以解决烧瓶安全问题并更改线路(第121行)

user = self.find_user(email=user)

user = self.find_user(username=user)

然后从repo重新安装flask-security(卸载flask-security然后安装)

pip install git+https://github.com/your_repo/flask-security

我亲自完成了很多自定义工作并且工作正常。请注意,您需要在需要修改角色时随时使用用户名

答案 1 :(得分:0)

使用来自flask-security网站的3个表,角色表不包含在您的示例中。我不是在这里包括'每个细微差别',只是代码的关键部分。我将User表重命名为Users,因为某些数据库存在命名冲突。因为您提供的是查询,您显然可以查询用户名或电子邮件(我正在使用电子邮件)。

你的____init____.py(或app.py)

中的

from flask_security import Security, SQLAlchemyUserDatastore


def create_app():
    user_datastore = SQLAlchemyUserDatastore(db, Users, Role)
    security = Security(app, user_datastore,
                        confirm_register_form=ExtendedConfirmRegisterForm)

    return app

models.py

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


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


class Users(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(50), unique=True)
    name = db.Column(db.String(30))
    password = db.Column(db.String(255))
    about = db.Column(db.String(255))
    last_login_at = db.Column(db.DateTime())
    current_login_at = db.Column(db.DateTime())
    last_login_ip = db.Column(db.String(100))
    current_login_ip = db.Column(db.String(100))
    login_count = db.Column(db.Integer)
    active = db.Column(db.Boolean())
    confirmed_at = db.Column(db.DateTime())

    roles = db.relationship('Role', secondary=roles_users,
                            backref=db.backref('users', lazy='dynamic'))

views.py

from app import db, create_app

app = create_app()
app.app_context().push()
security = app.extensions.get('security')
在views.py中查询

用户和角色

u = Users.query.filter_by(email='test@example.com').first()
r = Role.query.filter_by(name='test').first()
security.datastore.add_role_to_user(u, r)
db.session.commit()

答案 2 :(得分:-1)

您需要将add_role_to_user电子邮件作为字符串或用户实体本身传递。因此,您可以通过用户名获取用户,然后将该用户实体发送到add_role_to_user

user_datastore.add_role_to_user(my_user, 'site-admin')