I am currently diving into a flask project and try to use flask-admin for the first time. Everything is working fine so far, but one thing really bothers me: Whenever I edit my User model the users password gets overwritten. I am following the advice given in the second answer of this question to prevent flask-admin from re-hashing my password. Unfortunately the emptied password field still gets written to the database.
I tried to get the current password from the User
-Model which is given as a parameter to the on_model_change
method, but somehow the password seems to be already overwritten at that point (or it is not the actual database model I am looking at here - I am a little bit confused here).
Here is what my code looks like:
User-Model
class User(UserMixin, SurrogatePK, Model):
"""A user of the app."""
__tablename__ = 'users'
username = Column(db.String(80), unique=True, nullable=False)
email = Column(db.String(80), unique=True, nullable=False)
#: The hashed password
password = Column(db.String(128), nullable=True)
created_at = Column(db.DateTime, nullable=False,
default=datetime.datetime.utcnow)
first_name = Column(db.String(30), nullable=True)
last_name = Column(db.String(30), nullable=True)
active = Column(db.Boolean(), default=False)
is_admin = Column(db.Boolean(), default=False)
def __init__(self, username="", email="", password=None, **kwargs):
"""Create instance."""
db.Model.__init__(self, username=username, email=email, **kwargs)
if password:
self.set_password(password)
else:
self.password = None
def __str__(self):
"""String representation of the user. Shows the users email address."""
return self.email
def set_password(self, password):
"""Set password"""
self.password = bcrypt.generate_password_hash(password)
def check_password(self, value):
"""Check password."""
return bcrypt.check_password_hash(self.password, value)
def get_id(self):
"""Return the email address to satisfy Flask-Login's requirements"""
return self.id
@property
def full_name(self):
"""Full user name."""
return "{0} {1}".format(self.first_name, self.last_name)
@property
def is_active(self):
"""Active or non active user (required by flask-login)"""
return self.active
@property
def is_authenticated(self):
"""Return True if the user is authenticated."""
if isinstance(self, AnonymousUserMixin):
return False
else:
return True
@property
def is_anonymous(self):
"""False, as anonymous users aren't supported."""
return False
Flask-Admin UserView
class UserView(MyModelView):
"""Flask user model view."""
create_modal = True
edit_modal = True
def on_model_change(self, form, User, is_created):
if form.password.data is not None:
User.set_password(form.password.data)
else:
del form.password
def on_form_prefill(self, form, id):
form.password.data = ''
Any help is highly appreciated. Thanks in advance,
oneiro
User
-Model which flask-admin somehow wouldn't want me to do. I will definitely try to make your advice work, though. Thanks. – Brindisi