【发布时间】:2020-06-27 01:38:00
【问题描述】:
编辑(试图澄清问题):
我为我的烧瓶应用程序创建的用于检查重复用户名和电子邮件的自定义验证器不适用于管理员用户修改其他用户帐户。当管理员用户编辑另一个用户的用户名或电子邮件时,验证器会指示它是重复的,因为它正在尝试比较当前(管理员)用户的用户名和电子邮件,而不是正在编辑的用户的用户名和电子邮件。如何编写自定义验证器以使用传递给下面视图函数中的表单的用户对象来比较正在编辑的用户而不是登录用户的用户名和电子邮件?
原帖:
我正在开发一个 Flask 应用程序,该应用程序允许具有管理员权限的用户修改用户帐户信息。目前,我正在使用 Flask-WTF 和 WTForms 在用户个人资料页面上创建一个表单,帐户所有者或具有管理员权限的用户(通过用户模型中的角色分配)可以编辑用户信息。在视图函数中,我将用户信息传递给表单以使用用户信息预填充表单字段。当我为帐户所有者制作个人资料编辑表单时,提交表单时,我有一个自定义验证器,它将提交的数据与当前登录用户的数据进行比较,以检测是否编辑了任何字段,然后检查是否有这些字段(如用户名、电子邮件等)已经在数据库中以避免重复。对于管理员用户可以编辑其他用户的表单,此验证器一直阻止向数据库写入新值,因为验证器将登录的用户信息与数据库进行比较,而不是属于正在编辑的帐户的用户信息。我想知道在提交表单时如何将用于填充表单字段的用户对象传递给表单验证? Flask 应用程序使用的是蓝图结构。我对此很陌生,所以我希望这个问题是有道理的。这是一些我认为有用的代码。
这里是视图函数:
# Edit account view function for admin users
@users.route('/edit-account/<int:user_id>', methods=['GET', 'POST'])
@login_required
def edit_account(user_id):
# Get the info for the user being edited
user = User.query.get_or_404(user_id)
# Check to be sure user has admin privileges
if current_user.role != 'admin' and current_user.role != 'agent':
abort(403)
form = AccountEditForm()
if form.validate_on_submit():
# Update the profile picture, if a file is submitted
if form.profile_pic.data:
picture_file = save_picture(form.profile_pic.data)
user.profile_pic = picture_file
# Update the database entries for the user
user.username = form.username.data
user.first_name = form.first_name.data
user.last_name = form.last_name.data
user.email = form.email.data
user.role = form.role.data
db.session.commit()
flash(f'The account for {user.first_name} {user.last_name} has been updated.', 'success')
return redirect(url_for('users.users_admin'))
# Pre-populate the form with existing data
elif request.method == 'GET':
form.username.data = user.username
form.first_name.data = user.first_name
form.last_name.data = user.last_name
form.email.data = user.email
form.role.data = user.role
image_file = url_for('static', filename=f'profile_pics/{user.profile_pic}')
return render_template('account.html', title='account',
image_file=image_file, form=form, user=user)
当管理员用户尝试编辑另一个用户的帐户时,以下是不适用于验证器的表单类:
class AccountEditForm(FlaskForm):
username = StringField('Username',
validators=[DataRequired(), Length(min=2, max=20)])
first_name = StringField('First Name',
validators=[DataRequired(), Length(min=2, max=32)])
last_name = StringField('Last Name',
validators=[DataRequired(), Length(min=2, max=32)])
email = StringField('Email',
validators=[DataRequired(), Email()])
profile_pic = FileField('Update Profile Picture',
validators=[FileAllowed(['jpg', 'png'])])
role = SelectField('Role', validators=[DataRequired()],
choices=[('admin', 'Admin'), ('agent', 'Agent'), ('faculty', 'Faculty'),
('staff', 'Staff'), ('student', 'Student')])
submit = SubmitField('Update')
# Custom validation to check for duplicate usernames
def validate_username(self, username):
# Check to see if the form data is different than the current db entry
if username.data != username:
# Query db for existing username matching the one submitted on the form
user = User.query.filter_by(username=username.data).first()
if user:
raise ValidationError('Username is taken, please choose another.')
# Custom validation to check for duplicate email
def validate_email(self, email):
# Check to see if the form data is different than the current db entry
if email.data != user.email:
# Query db for existing email matching the one submitted on the form
user = User.query.filter_by(email=email.data).first()
if user:
raise ValidationError('Email is already used, please choose another or login.')
当用户从不同的表单类编辑自己的帐户时,这是一个自定义验证器:
# Custom validation to check for duplicate usernames
def validate_username(self, username):
# Check to see if the form data is different than the current db entry
if username.data != current_user.username:
# Query db for existing username matching the one submitted on the form
user = User.query.filter_by(username=username.data).first()
if user:
raise ValidationError('Username is taken, please choose another.')
# Custom validation to check for duplicate email
def validate_email(self, email):
# Check to see if the form data is different than the current db entry
if email.data != current_user.email:
# Query db for existing email matching the one submitted on the form
user = User.query.filter_by(email=email.data).first()
if user:
raise ValidationError('Email is already used, please choose another or login.')
【问题讨论】:
-
尝试添加一段说明您面临的问题。
-
当然,我尝试编辑以澄清问题。
标签: python flask flask-wtforms