如何在wtforms验证中使用来自视图函数的查询变量

时间:2020-10-04 10:55:18

标签: python validation flask flask-wtforms wtforms

情况:

我当前正在尝试验证EditProfile表单。 在这种情况下,我需要能够访问位于form.py中的wtforms中在视图函数中创建的用户变量,以验证名称输入与当前名称不同。用户的值,如果不是,则对它运行查询以检查它是否已经在系统中引发验证错误。

代码

routes.py

    @bp.route('/edit_user/<name>', methods=['GET', 'POST']) 
    @login_required
    @group_required(['Master', 'Upper Management', 'Management'])
    def edit_user(name):
    
        user = User.query.filter_by(name=name).first()
        academy = Academy.query.filter_by(id=user.id).first()
        trained = TrainedIn.query.filter_by(teacher=user.id).all()
        
        form = EditProfileForm(obj=user)
    
        if form.validate_on_submit():
            
            if user.name != form.name.data:
                new = User.query.filter_by(name=form.name.data).first()
                if new is not None:
                    raise ValidationError('Name already in use.')
            
            if user.phone != form.phone.data:
                new = User.query.filter_by(phone=form.phone.data).first()
                if new is not None:
                    raise ValidationError('Phone number already in use.')
    
            if user.email != form.email.data:
                new = User.query.filter_by(email=form.email.data).first()
                if new is not None:
                    raise ValidationError('Email already in use.')
    
            
    
            return redirect(url_for('edit_user', name=user.name))
    
        elif not form.is_submitted():
    
            form.name.data = user.name
            form.phone.data = user.phone
            form.email.data = user.email
            form.position.data = user.position
            form.academy.data = academy.name
            form.trained.data = [t.name for t in trained] 
            
        return render_template('edit_user.html', title='Edit User',user=user, form=form)

在这里,我有那些if语句来尝试验证,但是,它不能令人满意,因此希望将它们移到当前时间的表单验证中。

forms.py

class EditProfileForm(FlaskForm):

name = StringField('Full Name', validators=[DataRequired()])
phone = StringField('Phone Number', validators=[DataRequired()])
email = StringField('Email', validators=[DataRequired(), Email()])
position = SelectField('Position', validators=[DataRequired()], choices=[
    ('Upper Management', 'Upper Management'),
    ('Management', 'Management'), 
    ('Admin','Admin'), 
    ('Teacher','Teacher')])
academy = SelectField('Academy', validators=[DataRequired()], choices=[
    ('Alonso Martínez','Alonso Martínez'),
    ('Argüelles','Argüelles')
    ])
trained = SelectMultipleField('Trained to teach', choices=[
    ('General English', 'General English'),
    ('Exam', 'Exam'),
    ('Children', 'Children'),
    ('Level Test', 'Level Test')
    ])
submit = SubmitField('Confirm')

def validate_phone(self, phone):
    try:
        p = phonenumbers.parse(phone.data)
        if not phonenumbers.is_valid_number(p):
            raise ValueError()
    except (phonenumbers.phonenumberutil.NumberParseException, ValueError):
        raise ValidationError('Invalid phone number')

我的目标

我的目的是以某种方式将用户变量发送到form.py,以便能够使用类似于以下内容的自定义验证对其进行验证:

    def validate_name(self, name):
    if name != user.name:
        user1 = User.query.filter_by(name=name).first()
        if user1 is not None:
            raise ValidationError('Name already in use.')

我所做的事情:

  1. 我尝试放置可自动归档的obj = user 值,但不允许我访问该变量。
  2. 我试图将用户项目放入烧瓶的'g'变量中,但是 这似乎不起作用,也不是一个好主意 考虑到使用该应用程序的多个人可能以g结尾 变量同时设置。

更多信息:

我无法使用flask-login中的current_user变量,因为编辑配置文件的人将不是用户,而是拥有更高权限链的人。因此,为什么我认为最好的方法是将已创建的用户变量发送到wtforms以进行验证。

问题:

所有这一切中的主要问题是,如何从视图向表单发送一个保存了查询的变量以进行验证,如果不可能的话,最好的验证方法是什么这样一来,用户就可以知道发生了什么,而不会引发内部错误。

1 个答案:

答案 0 :(得分:0)

答案是将变量发送到表单构造函数,然后从那里将变量设置为表单构造函数的属性。即

routes.py

#include <memory>

using namespace std;

class O {
public:
    O() {}
};

struct A : virtual public O {
};

struct B : virtual O {
    B() {}
    void GetShared() {
    }
};

struct C : std::enable_shared_from_this<C>, A, B {
    C() = default;
};

int main()
{
    std::shared_ptr<B> pt = std::make_shared<C>();
    pt->GetShared();
}

forms.py

form = EditProfileForm(obj=user.id)