1

So I created a basic Flask-User app with multiple roles and datastructure like this:

class User(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    active = db.Column('is_active', db.Boolean(), nullable=False, server_default='0')
    first_name = db.Column(db.String(50), nullable=False, default='')
    last_name = db.Column(db.String(50), nullable=False, default='')
    email = db.Column(db.String(255), nullable=False, unique=True)
    confirmed_at = db.Column(db.DateTime())
    # Relationships
    user_auth = db.relationship('UserAuth', uselist=False)
    roles = db.relationship('Role', secondary='user_roles',
            backref=db.backref('users', lazy='dynamic'))

    def is_active(self):
        return self.active

class UserAuth(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer(), db.ForeignKey('user.id', ondelete='CASCADE'))

    # User authentication information
    username = db.Column(db.String(50), nullable=False, unique=True)
    password = db.Column(db.String(255), nullable=False, default='')

    # Relationships
    user = db.relationship('User', uselist=False)

    def hash_password(self, password):
        self.password_hash = pwd_context.encrypt(password)

    def verify_password(self, password):
        return pwd_context.verify(password, self.password_hash)

class Role(db.Model):
    id = db.Column(db.Integer(), primary_key=True)
    name = db.Column(db.String(50), unique=True)

class UserRoles(db.Model):
    id = db.Column(db.Integer(), primary_key=True)
    user_id = db.Column(db.Integer(), db.ForeignKey('user.id', ondelete='CASCADE'))
    role_id = db.Column(db.Integer(), db.ForeignKey('role.id', ondelete='CASCADE'))

I try to show it in Flask-Admin:

class AdminView(ModelView):
    def is_accessible(self):
        access = current_user.is_authenticated and current_user.has_role('admin')
        return access

admin = Admin(app, name='My Admin', template_mode='bootstrap3')
admin.add_view(AdminView(User, db.session))
admin.add_view(AdminView(UserAuth, db.session))
admin.add_view(AdminView(Role, db.session))
admin.add_view(AdminView(UserRoles, db.session))

Why It shows in such a strange manner: enter image description here enter image description here

And how to see and be able to edit user roles when editing a user?

DuckQueen
  • 772
  • 10
  • 62
  • 134

1 Answers1

2

You have not defined a suitable string representation for instances of your UserAuth class. A suitable example would be:

class UserAuth(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer(), db.ForeignKey('user.id', ondelete='CASCADE'))

    # User authentication information
    username = db.Column(db.String(50), nullable=False, unique=True)
    password = db.Column(db.String(255), nullable=False, default='')

    # Relationships
    user = db.relationship('User', uselist=False)

    def hash_password(self, password):
        self.password_hash = pwd_context.encrypt(password)

    def verify_password(self, password):
        return pwd_context.verify(password, self.password_hash)

    def __str__(self):
        return unicode(self).encode('utf-8')

    def __unicode__(self):
        return self.username

This needs to be done for all your models.

pjcunningham
  • 7,676
  • 1
  • 36
  • 49
  • 1
    To show roles as list of strings addition of `column_auto_select_related = True` to the `View` and `__str__` and `__hash__` to the `Role` classes was enough for me. – DuckQueen Aug 05 '17 at 10:39