how to use flask-admin for editing modelview

和自甴很熟 提交于 2019-11-29 15:21:04

问题


How to set password_hash using generate_password_hash from the edit page of flask-admin

  1. i create a username and password in python shell. the password is hashing
  2. admin.add_view(MyModelView(User, db.session) - let me edit the User class Models
  3. when i edit the password and submit but the password is saved in plain text.

How to edit password from flask-admin, the password should be save in hashing type

My code is:

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()

回答1:


Alternative solution is to subclass a TextField adding custom processing logic:

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',
        ),
    )



回答2:


i solved my problem by using on_model_change function in flask-admin

#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



回答3:


Simpler solution, you don't need to subclass TextField

Just add 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 = ''

This will prevent double-hashing.




回答4:


I tried the solutions outlined in some of the other answers and I was only partially successful. There were issues with being able to edit the user later, and the password rehashing, or disappearing altogether.

One discovery I made was that on_model_change actually gets called AFTER the model is populated from the form. There is no way to access the old values of the model without querying the database or monkey patching update_model.

I have come up with a simpler version (I believe) that works in all scenarios.

Here is the whole view:

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)

What I did was add a form field set_password which when populated creates a password hash and updates password on the model.

One and done!



来源:https://stackoverflow.com/questions/28970076/how-to-use-flask-admin-for-editing-modelview

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!