返回介绍

修复用户名重复的 BUG

发布于 2025-01-02 21:53:51 字数 1604 浏览 0 评论 0 收藏 0

利用用户名重复 BUG 这么久, 现在时候向你展示如何修复它了。

你是否还记得, RegistrationForm 已经实现了对用户名的验证,但是编辑表单的要求稍有不同。 在注册期间,我需要确保在表单中输入的用户名不存在于数据库中。 在编辑个人资料表单中,我必须做同样的检查,但有一个例外。 如果用户不改变原始用户名,那么验证应该允许,因为该用户名已经被分配给该用户。 下面你可以看到我为这个表单实现了用户名验证:

class EditProfileForm(FlaskForm):
    username = StringField('Username', validators=[DataRequired()])
    about_me = TextAreaField('About me', validators=[Length(min=0, max=140)])
    submit = SubmitField('Submit')

    def __init__(self, original_username, *args, **kwargs):
        super(EditProfileForm, self).__init__(*args, **kwargs)
        self.original_username = original_username

    def validate_username(self, username):
        if username.data != self.original_username:
            user = User.query.filter_by(username=self.username.data).first()
            if user is not None:
                raise ValidationError('Please use a different username.')

该实现使用了一个自定义的验证方法,接受表单中的用户名作为参数。 这个用户名保存为一个实例变量,并在 validate_username() 方法中被校验。 如果在表单中输入的用户名与原始用户名相同,那么就没有必要检查数据库是否有重复了。

为了使得新增的验证方法生效,我需要在对应视图函数中添加当前用户名到表单的 username 字段中:

@app.route('/edit_profile', methods=['GET', 'POST'])
@login_required
def edit_profile():
    form = EditProfileForm(current_user.username)
    # ...

现在这个 BUG 已经修复了,大多数情况下,以后在编辑个人资料时出现用户名重复的提交将被友好地阻止。 但这不是一个完美的解决方案,因为当两个或更多进程同时访问数据库时,这可能不起作用。假如存在验证通过的进程 A 和 B 都尝试修改用户名为同一个,但稍后进程 A 尝试重命名时,数据库已被进程 B 更改,无法重命名为该用户名,会再次引发数据库异常。 除了有很多服务器进程并且非常繁忙的应用之外,这种情况是不太可能的,所以现在我不会为此担心。

此时,你可以尝试再次重现该错误,以了解新的表单验证方法如何防止该错误。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文