Flask:在多个表单字段上进行条件验证


问题内容

让我从平常开始-我是Python和Flask的新手。在发布这个问题之前(我的第一个问题),我已经花费了数小时进行搜索和试验,但到目前为止还没有运气。

我正在构建Web表单,用户可以在其中定义防火墙规则,这些规则随后会记录在数据库中。我正处于验证阶段,在这里碰到了墙…希望有人能够帮助我。

我的表单(这里简化)有2个字段-src_ip和dst_ip:

class FirewallRule(Form)
    src_ip = StringField('Source IP')
    dst_ip = StringField('Destination IP')

我的验证要求是:

  1. 至少必须填写1个字段(都可以)
  2. 填写的字段必须包含有效的IP地址

wtforms.validators.IPAddress()和自定义验证功能似乎是我的朋友,但是我正在努力寻找一种将它们连接在一起的方法。

本质上,我正在尝试建立条件验证:

  1. 如果不是(src_ip或dst_ip);返回False
  2. 如果src_ip和src_ip无效的IP地址;返回False
  3. 如果dst_ip和dst_ip无效的IP地址;返回False
  4. 返回真

显然,我想重用IPAddress()[或通常使用任何内置的验证器],而不是自己编写。

我确信有人一定曾经做过。不幸的是,我找不到正确方向的任何指针。

提前致谢。


问题答案:

您缺少一个非常有用的验证器:Optional。该验证器允许您说一个字段可以为空,但如果该字段不为空,则应使用其他验证器。

关于填写至少一个字段的部分,我将使用自定义验证方法来完成,我认为没有任何股票验证器可以帮助您解决这一问题。

所以会是这样的:

class FirewallRule(Form)
    src_ip = StringField('Source IP', validators=[Optional(), IPAddress()])
    dst_ip = StringField('Destination IP', validators=[Optional(), IPAddress()])

    def validate(self):
        if not super(FirewallRule, self).validate():
            return False
        if not self.src_ip.data and not self.dst_ip.data:
            msg = 'At least one of Source and Destination IP must be set'
            self.src_ip.errors.append(msg)
            self.dst_ip.errors.append(msg)
            return False
        return True

如果要避免使用自定义验证功能,请考虑创建一个验证器类来检查是否已设置字段列表中的至少一个是相当容易的。如果您想遵循此路线,可以查看EqualTo验证器的实现以获取启发。