代码体系结构 - Flask - 从数据库中进行表单验证的位置?

时间:2016-05-14 14:24:34

标签: validation flask architecture wtforms web-architecture

我想知道我应该在哪里放置一个访问数据库的验证表单。 基本上我需要用户输入item_type,我想首先检查数据库中是否存在item_type

有3种选择:

  1. 在数据库模型中,我有ItemType类,我放了函数add(),它会检查现有项是否存在

  2. 在视图中,所以在页面路径中,从wtforms form.validate_on_submit()开始,我会检查从数据库中获取数据,如果存在,我会把错误放在这里

  3. 在wtforms validate()中,在Form类的默认验证后添加额外验证

  4. 我见过人们使用2号和3号,但不确定哪一个是最好的。我想要的错误消息也需要在表单的特定字段上显示它(这可以通过方法2和3实现,因为它们引用了表单字段)但是又因为它与访问数据库有关,也许它最好将关于数据库访问的所有内容都放到模型函数中吗?

1 个答案:

答案 0 :(得分:2)

在我看来,如果它来自一个表单,那么它应该在该表单上进行验证,然后在无效时针对该特定字段引发错误。请参见下面的示例:

class SigninForm(Form):
    """Form for signin"""
    email = StringField('Email',
                        validators=[
                            DataRequired("Email shouldn't be empty."),
                            Email('Email format is not correct.')
                        ])

    password = PasswordField('Password',
                             validators=[DataRequired("Password shouldn't be empty.")])

    def validate_email(self, field):
        """ 
            verify if account exists and if not raise an error in
            that field. 
        """
        user = User.query.filter(User.email == self.email.data).first()
        if not user:
            raise ValueError("Account doesn't exist.")

    def validate_password(self, field):
        """ 
            Verify if password is valid and if not raise an error in
            that field. 
        """
        if self.email.data:
            user = User.query.filter(User.email == self.email.data).first()
            if not user or not user.check_password(self.password.data):
                raise ValueError('Password is not correct.')
            else:
                self.user = user

此示例的视图函数:

@app.route('/signin', methods=['GET', 'POST'])
def signin():
    """Signin"""
    form = SigninForm()
    if form.validate_on_submit():
        # sign in function to register user into a session
        signin_user(form.user)
        return redirect(url_for('site.index'))
    return render_template('account/signin/signin.html', form=form)