WTForms пропускают проверку, если данные поля не изменились

#python #flask #flask-wtforms #wtforms

#python #flask #колба-wtforms #wtforms

Вопрос:

У меня есть веб-приложение Flask, которое управляет информацией всех киосков. Я создал объект WTForms для информации киоска (forms.py ):

 class KioskForm(FlaskForm):
    kiosk_name = StringField('Kiosk Name', validators=[DataRequired()])
    kiosk_site = SelectField('Kiosk's Site', validators=[DataRequired()])
    kiosk_location = StringField(
        'Kiosk's Location', validators=[DataRequired()])
    kiosk_ip = StringField('IP Address', validators=[
        IPAddress(), DataRequired()])
    kiosk_mac = StringField('MAC Address', validators=[DataRequired()])
    submit = SubmitField('Submit')

    def validate_kiosk_name(self, kiosk_name):
        kiosk = db.session.query(KioskConf).filter_by(
            equipment_name=self.kiosk_name.data).first()

        if kiosk is not None:
            raise ValidationError('Kiosk Name existed.')
 

Предположим, я хочу отредактировать информацию о существующем киоске (routes.py ):

 @app.route('/edit_kiosk/<kiosk_name>', methods=['GET', 'POST'])
def edit(kiosk_name):
    data = db.session.query(KioskConf).filter_by(
        equipment_name=kiosk_name).first()

    form = KioskForm(kiosk_name=data.equipment_name,
                     kiosk_location=data.equipment_location,
                     kiosk_ip=data.equipment_ip,
                     kiosk_mac=data.equipment_mac)
    ... ...
 

Что я хотел сделать, так это: если кто-то изменил название киоска на другое существующее, он будет жаловаться, что название уже существует. Который проверка находится в forms.py .

Но одна проблема заключается в том, что если я отредактировал существующий киоск, возможно, изменил IP-адрес, но имя осталось прежним, после отправки жалобы имя уже существует. Что-то должно быть не так с проверкой имени здесь.

Как заставить WTForms пропустить проверку имени, если имя не изменилось?

Ответ №1:

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

 
def initializeKioskForm(edit_boolean):
    # only validate if edit_boolean is false
    if edit_boolean == False:
        kiosk = db.session.query(KioskConf).filter_by(
            equipment_name=self.kiosk_name.data).first()
        if kiosk is not None:
            raise ValidationError('Kiosk Name existed.')
    
    class KioskForm(FlaskForm):
        kiosk_name = StringField('Kiosk Name', validators=[DataRequired()])
        kiosk_site = SelectField('Kiosk's Site', validators=[DataRequired()])
        kiosk_location = StringField(
            'Kiosk's Location', validators=[DataRequired()])
        kiosk_ip = StringField('IP Address', validators=[
            IPAddress(), DataRequired()])
        kiosk_mac = StringField('MAC Address', validators=[DataRequired()])
        submit = SubmitField('Submit')

    return KioskForm
 

 
from forms import initialize_controller_form

@app.route('/edit_kiosk/<kiosk_name>', methods=['GET', 'POST'])
def edit(kiosk_name):
    data = db.session.query(KioskConf).filter_by(
        equipment_name=kiosk_name).first()

    KioskForm = initializeKioskForm(edit_boolean=True)
    form = KioskForm(kiosk_name=data.equipment_name,
                        kiosk_location=data.equipment_location,
                        kiosk_ip=data.equipment_ip,
                        kiosk_mac=data.equipment_mac)

 

Комментарии:

1. Похоже, что приведенная выше логика заключается в том, чтобы дать разработчику «переключатель», нужно ли формам выполнять проверку или нет при инициализации формы, вместо проверки того, были ли изменены исходные данные поля.

Ответ №2:

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

В forms.py , добавить инициализатор для хранения исходных данных поля и использовать для сравнения новых данных:

 class KioskForm(FlaskForm):
    kiosk_name = StringField('Kiosk Name', validators=[DataRequired()])
    kiosk_site = SelectField('Kiosk's Site', validators=[DataRequired()])
    kiosk_location = StringField(
        'Kiosk's Location', validators=[DataRequired()])
    kiosk_ip = StringField('IP Address', validators=[
        IPAddress(), DataRequired()])
    kiosk_mac = StringField('MAC Address', validators=[DataRequired()])
    submit = SubmitField('Submit')

    # Initialiser
    def __init__(self, original_name, *args, **kwargs):
        super(KioskForm, self).__init__(*args, **kwargs)
        self.original_name = original_name

    # Changed to compare the old amp; new data
    def validate_kiosk_name(self, kiosk_name):
        if kiosk_name.data != self.original_name:
            kiosk = db.session.query(KioskConf).filter_by(
                equipment_name=self.kiosk_name.data).first()
            if kiosk is not None:
                raise ValidationError('Kiosk ID existed.')
 

И в routes.py , введите исходное имя в original_name:

 @app.route('/edit_kiosk/<kiosk_name>', methods=['GET', 'POST'])
def edit(kiosk_name):
    data = db.session.query(KioskConf).filter_by(
        equipment_name=kiosk_name).first()

    form = KioskForm(kiosk_name=data.equipment_name,
                     kiosk_location=data.equipment_location,
                     kiosk_ip=data.equipment_ip,
                     kiosk_mac=data.equipment_mac,
                     original_name=data.equipment_name
)
    ... ...