I have an app making by Flask and for database management I using Flask-admin and Flask-SQLAlchemy. And in my app there has three role, which is:
here is the snipet of code on my table:
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 Role(db.Model, RoleMixin):
id = db.Column(db.Integer(), primary_key=True)
name = db.Column(db.String(80), unique=True)
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(255))
roles = db.relationship('Role', secondary=roles_users,
backref=db.backref('users', lazy='dynamic'))
class School(User):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
class Parent(User):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
school_id = db.Column(db.Integer, db.ForeignKey('school.id'))
The code already works fine.
I can set the role for all of the users manually with Flask-admin interface, I can make it with a user that has admin role.
But, for the user that has school role, I don't give access to set the role like admin does.
What I want is when the user that has school role make an account, it automatically set the role to parent.
In my ModelView, I try to insert it with this code:
class ParentModelView(sqla.ModelView):
def on_model_change(self, form, model, is_created):
if is_created:
model.school_id = current_user.id
model.roles = 'parent'
and then I got this error:
TypeError: Incompatible collection type: str is not list-like
and then I try to wraping it with list:
def on_model_change(self, form, model, is_created):
if is_created:
model.school_id = current_user.id
model.roles = ['parent']
then the error be like this:
AttributeError: 'str' object has no attribute '_sa_instance_state'
And when I try to set the default value on my relationship column :
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(255))
roles = db.relationship('Role', secondary=roles_users,
backref=db.backref('users', lazy='dynamic'),
default='parent') # or default=3 (which is '3' is the parent id in roles_user association table.
and then I got this error:
TypeError: relationship() got an unexpected keyword argument 'default'
So, the point what I want is to set a default value on my relationship column that defines roles users.
Any help will be much appreciated.
In your code you are trying to assign the string 'parent' when you should be assigning a list of Role
instances.
In your on_model_change
method you need to fetch the role that has name 'Parent' from the database and then assign it to the roles relationship as a list.
Example (untested)
def on_model_change(self, form, model, is_created):
if is_created:
# find the role with name 'Parent'
_parent_role = Role.query.filter(Role.name == 'Parent').first()
if _parent_role:
model.school_id = current_user.id
model.roles = [_parent_role]