Как использовать переменную запроса из функции просмотра при проверке wtforms

#python #validation #flask #flask-wtforms #wtforms

#python #проверка #flask #flask-wtforms #wtforms

Вопрос:

Ситуация:

В настоящее время я пытаюсь проверить форму EditProfile. При этом мне нужно иметь доступ к пользовательской переменной, которую я создал в функции просмотра в wtforms, которая находится в forms.py , чтобы проверить, что введенное имя не совпадает с тем, которое является текущим значением для пользователя, и если это не так, то запуститезапросите ее, чтобы проверить, есть ли она уже в системе, чтобы выдать ошибку проверки.

Код

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')
  

Моя цель

Моя цель — каким-то образом отправить пользовательскую переменную в forms.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’ из flask, но это, похоже, не работает и не кажется хорошей идеей, учитывая, что несколько человек, использующих приложение, могут одновременно установить переменную g.

Немного больше информации:

Я не могу использовать переменную current_user из flask-login, поскольку человек, редактирующий профиль, будет не пользователем, а кем-то с более высоким уровнем в цепочке разрешений. Поэтому я считаю, что лучший способ — отправить пользовательскую переменную, которая была создана в wtforms, для обработки при проверке.

Вопрос:

Главный вопрос во всем этом заключается в том, как я могу отправить переменную, в которой сохранен запрос, из представления в форму для проверки, и если это невозможно, каков наилучший способ проверить это таким образом, чтобы пользователь мог знать, что происходит, не просто проверяя, что происходит.выдает внутреннюю ошибку.

Ответ №1:

Ответ состоял в том, чтобы отправить переменную в конструктор формы, а затем оттуда установить переменную в качестве атрибута конструктора формы. т.е.

routes.py

 form = EditProfileForm(obj=user.id)
  

forms.py

 def __init__(self, obj, *args, **kwargs):
        self.user = int(obj)
        super(EditProfileForm, self).__init__(*args, **kwargs)