如何使用flask-admin的编辑页面中的generate_password_hash设置password_hash
如何从flask-admin编辑密码,密码应保存为散列类型
我的代码是:
from werkzeug.security import generate_password_hash, check_password_hash
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(120))
password_hash = db.Column(db.String(64))
username = db.Column(db.String(64), unique=True, index=True)
@password.setter
def password(self, password):
self.password_hash = generate_password_hash(password)
def __repr__(self):
return '<User %r>' % self.username
#Create custom models view
class MyModelView(sqla.ModelView):
@admin.expose('/login/')
def index(self):
return self.render('login.html')
# Create custom admin view
class MyAdminView(admin.BaseView):
@admin.expose('/')
def index(self):
return self.render('myadmin.html')
admin = admin.Admin(name="Simple Views")
admin.add_view(MyAdminView(name='hello'))
admin.add_view(MyModelView(User, db.session))
admin.init_app(app)
app.run()
答案 0 :(得分:7)
替代解决方案是继承TextField
添加自定义处理逻辑:
class MyPassField(TextField):
def process_data(self, value):
self.data = '' # even if password is already set, don't show hash here
# or else it will be double-hashed on save
self.orig_hash = value
def process_fromdata(self, valuelist):
value = ''
if valuelist:
value = valuelist[0]
if value:
self.data = generate_password_hash(value)
else:
self.data = self.orig_hash
class UserView(ModelView):
form_overrides = dict(
passhash=MyPassField,
)
form_widget_args = dict(
passhash=dict(
placeholder='Enter new password here to change password',
),
)
答案 1 :(得分:4)
我通过在flask-admin
中使用on_model_change函数解决了我的问题#Create custom models view
class MyModelView(sqla.ModelView):
@admin.expose('/login/')
def index(self):
return self.render('login.html')
def on_model_change(self, form, User, is_created=False):
User.password = form.password_hash.data
答案 2 :(得分:3)
更简单的解决方案,您不需要继承TextField
只需添加on_form_prefill
:
def on_model_change(self, form, User, is_created):
if form.password_hash.data:
User.set_password(form.password_hash.data)
else:
del form.password_hash
def on_form_prefill(self, form, id):
form.password_hash.data = ''
这样可以防止双重散列。
答案 3 :(得分:2)
我尝试了其他一些答案中概述的解决方案,但我只取得了部分成功。以后能够编辑用户,密码重新编码或完全消失存在问题。
我做的一个发现是,on_model_change
实际上是在从表单填充模型后调用的。如果不查询数据库或猴子修补update_model
,则无法访问模型的旧值。
我想出了一个更简单的版本(我相信),适用于所有场景。
以下是整个观点:
class UserView(AdminModel):
can_create = True
column_list = ('name', 'email',)
column_searchable_list = ('name', 'email',)
form_excluded_columns = ('password',)
form_extra_fields = {
'set_password': PasswordField('Set New Password')
}
def on_model_change(self, form, model, is_created):
if is_created:
model.active = True
model.pending = False
if form.email.data:
# Strip spaces from the email
form.email = form.email.data.strip()
if form.set_password.data:
model.password = bcrypt.generate_password_hash(form.set_password.data.strip())
def __init__(self, session, **kwargs):
# You can pass name and other parameters if you want to
super(UserView, self).__init__(User, session, **kwargs)
我所做的是添加一个表单字段set_password
,填充时会创建一个密码哈希并更新模型上的password
。
一个完成!
答案 4 :(得分:0)
我的解决方案是简单地将列格式化程序字段添加到 UserView 模型,该模型返回所有表单字段的字典。然后选择使用 bcrypt 哈希格式化保存的密码。
class UserView(ModelView):
column_formatters =dict(password=lambda v,c,m,password: bcrypt.generate_password_hash(m.password, config.get('BCRYPT_LOG_ROUNDS')) \
.decode('utf-8'))
有关 lambda 函数采用的参数的更多详细信息,请参阅flaskAdmin 官方文档。column_formatters