编辑(试图澄清问题):
我为我的烧瓶应用程序创建的自定义验证器,用于检查重复的用户名和电子邮件,不适用于管理员用户修改其他用户帐户。当管理员用户编辑另一个用户的用户名或电子邮件时,验证器会指出它是重复的,因为它试图比较当前(管理员)用户的用户名和电子邮件,而不是正在编辑的用户的用户名和电子邮件。如何编写自定义验证器,以使用传递给下面的视图函数中的表单的用户对象,以比较正在编辑的用户的用户名和电子邮件,而不是已登录的用户?
原始帖子:
我正在开发Flask应用程序,该应用程序具有管理员权限的用户可以修改用户帐户信息。当前,我正在使用Flask-WTF和WTForms在用户个人资料页面上创建一个表单,帐户所有者或具有管理员特权的用户(通过用户模型中的角色分配)可以编辑用户信息。在视图功能中,我将用户信息传递给表单,以使用用户信息预填充表单字段。当我为帐户所有者制作个人资料编辑表单时,在提交表单时,我有一个自定义验证器,可将提交的数据与当前登录用户的数据进行比较,以检测是否有任何字段被编辑,然后检查是否有某些字段这些字段(例如用户名,电子邮件等)已经在数据库中,以避免重复。对于管理员用户可以编辑其他用户的表单,该验证器将继续防止将新值写入数据库,因为验证器会将登录的用户信息与数据库进行比较,而不是将属于正在编辑的帐户的用户信息与数据库进行比较。我想知道如何在提交表单时将用于填充表单字段的用户对象传递给表单验证?Flask应用程序正在使用蓝图结构。我对此很陌生,所以我希望这个问题有意义。这是一些我认为有帮助的代码。我想知道如何在提交表单时将用于填充表单字段的用户对象传递给表单验证?Flask应用程序正在使用蓝图结构。我对此很陌生,所以我希望这个问题有意义。这是一些我认为有帮助的代码。我想知道如何在提交表单时将用于填充表单字段的用户对象传递给表单验证?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.')
这是将对象传递给自定义验证器的示例,该方案与您的方案完全相同:
class EditProfileAdminForm(EditProfileForm):
email = StringField('Email', validators=[DataRequired(), Length(1, 254), Email()])
role = SelectField('Role', coerce=int)
active = BooleanField('Active')
confirmed = BooleanField('Confirmed')
submit = SubmitField()
def __init__(self, user, *args, **kwargs): # accept the object
super(EditProfileAdminForm, self).__init__(*args, **kwargs)
self.role.choices = [(role.id, role.name)
for role in Role.query.order_by(Role.name).all()]
self.user = user # set the object as class attr
def validate_username(self, field):
# use self.user.username to get the user's username
if field.data != self.user.username and User.query.filter_by(username=field.data).first():
raise ValidationError('The username is already in use.')
def validate_email(self, field):
if field.data != self.user.email and User.query.filter_by(email=field.data.lower()).first():
raise ValidationError('The email is already in use.')
# view function
@admin_bp.route('/profile/<int:user_id>', methods=['GET', 'POST'])
@login_required
@admin_required
def edit_profile_admin(user_id):
user = User.query.get_or_404(user_id)
form = EditProfileAdminForm(user=user) # pass the object
# ...
示例代码来自照片共享应用程序。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句