【问题标题】:WTForms skip validation if field data is unchanged如果字段数据未更改,WTForms 会跳过验证
【发布时间】:2020-11-20 04:08:57
【问题描述】:

我有一个管理所有信息亭信息的 Flask 网络应用程序。我为信息亭的信息(forms.py)创建了一个 WTForms 对象:

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 跳过名称验证?

【问题讨论】:

    标签: python flask flask-wtforms 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)
    
    

    【讨论】:

    • 看起来上面的逻辑是给开发者一个“开关”表单是否需要在表单初始化时执行验证,而不是检查原始字段数据是否已更改。
    【解决方案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 & 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
    )
        ... ...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-23
      • 2023-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多