【问题标题】:Is it possible to set conditional validation in cerberus, Python?是否可以在 cerberus、Python 中设置条件验证?
【发布时间】:2020-05-22 11:39:42
【问题描述】:

我使用 Python 包 cerberus 来验证我的有效载荷 这是我的问题:

仅当来自另一个模式的某些字段具有精确值时,我才需要设置一个字段。比如:

    "key2": {
      "type": "string",
      "required": \\\ true if dict1.key1 == 'valueX' else false \\\
    }

所以我的架构应该是这样的:

"dict1": {
  "type": "dict",
  "schema": {
    "key1": {
      "type": "string",
      "required": true
    }
  }
},
"dict2": {
  "type": "dict",
  "schema": {
    "key2": {
      "type": "string",
      "required": \\\ true if dict1.key1 == 'valueX' else false \\\
    }
  }
}

有人知道方法吗,如何实现? 谢谢

【问题讨论】:

    标签: python-3.x validation conditional-statements cerberus


    【解决方案1】:

    我已阅读文档,但没有找到答案。 在您的示例中,我不确定它是否真的有效。此外,我认为依赖项的工作方式与我的示例不同。但也许我错了。

    看起来子模式中的依赖项不起作用。 您的示例返回错误消息:

    from cerberus import Validator
    schema = {"dict1": {
            "type": "dict",
            "schema": {
                "key1": {
                    "type": "string",
                    "required": True,
                    "allowed": ["valueX"]
                }
            }
        },
        "dict2": {
            "type": "dict",
            "schema": {
                "key2": {  # required if dependency matches
                    "type": "string",
                    "dependencies": {
                        "dict1.key1": ["valueX"]
                    }
                }
            }
        }
    }
    payload = {
        "dict1": {
                    "key1": 'valueX'
                },
         "dict2": {
                    "key2": 'some_value'
                }       
        }
    
    validator = Validator(schema)
    if validator(payload):
        print('Super!')
    else:
        print(str(validator.errors))
    

    有错误:

    {'dict2': [{'key2': ["depends on these values: {'dict1.key1': ['valueX']}"]}]}
    

    但是当我尝试为“dict2”设置依赖项时它起作用了

    schema = {"dict1": {
            "type": "dict",
            "schema": {
                "key1": {
                    "type": "string",
                    "required": True#,
                    #"allowed": ["valueX"]
                }
            }
        },
        "dict2": {
            "type": "dict",
            "dependencies": {
                        "dict1.key1": "sms"
                    },
            "schema": {
                "key2": {  # required if dependency matches
                    "type": "string"
                }
            }
        }
    }
    

    如果我错了,请告诉我。该解决方案真的会帮助我。 谢谢

    【讨论】:

      【解决方案2】:

      我也在为此苦苦挣扎,这是一个较短的示例,我希望它可以使用依赖项来工作。我将其发布为答案(但社区 wiki),因为代码块在 cmets 中往往看起来不太好。希望没关系,而不是创建一个单独的问题。

      更短的可重现示例

      schema = {
          'field1': {
              'required': True
          }, 
          'field2': {
              'required': True,      
               'dependencies': {
                   'field1': 'one'
               }
          }
      }
      
      >>> document = {'field1': 'two'}
      >>> v.validate(document, schema)
      False
      >>> print(v.errors)
      
      {'field2': ['required field']}
      

      据我了解,如果字段 1 等于“一”,则需要执行上述操作。

      我的第二次尝试是不让它成为必需:

      schema = {
          'field1': {
              'required': True
          }, 
          'field2': {
              'required': False,      
               'dependencies': {
                   'field1': 'one'
               }
          }
      }
      

      但是通过了测试:

      >>> document = {'field1': 'one'}
      >>> v.validate(document, schema)
      True
      >>> print(v.errors)
      
      {}
      

      只有当“field1”没有批准的值时我尝试在“field2”中提供一个值时才会失败:

      >>> document = {'field1': 'two', 'field2': 'test'}
      >>> v.validate(document, schema)
      False
      >>> print(v.errors)
      
      {'field2': ["depends on these values: {'field1': 'one'}"]}
      

      所以我认为 Cerberus 不支持这个用例,或者如果支持,我还没有找到正确的组合。

      【讨论】:

        【解决方案3】:

        大多数时候,您会在图书馆的文档中找到解决方案。
        您正在寻找的是“dependencies

        可在此处找到 Cerberus 文档和相应部分的链接:
        https://docs.python-cerberus.org/en/stable/validation-rules.html#dependencies

        在文档中它说:


        提供映射时,不仅所有依赖项都必须存在,而且它们的任何允许值都必须匹配。


        还支持使用点符号声明对子文档字段的依赖关系:

        对于您的示例,这仅意味着,如果您的要求绑定到一个值,则该值必须与使用“允许”规则指定的任何值匹配。

        如果您的要求绑定到模式,则可以通过点表示法指定该模式及其子模式。

        应该适合您的解决方案如下所示:

        "dict1": {
            "type": "dict",
            "schema": {
                "key1": {
                    "type": "string",
                    "required": True,
                    "allowed": ["valueX"]
                }
            }
        },
        "dict2": {
            "type": "dict",
            "schema": {
                "key2": {  # required if dependency matches
                    "type": "string",
                    "dependencies": {
                        "dict1.key1": ["valueX"]
                    }
                }
            }
        }
        

        我不确定当您根本不指定任何“允许”规则时这是否也有效,但我几乎猜想它应该。

        【讨论】:

        • 感谢您的评论,但它不起作用(检查我从 tMay 26 开始的回答。如果我做错了什么,请告诉我。谢谢
        • 您在此处使用依赖项规则走在正确的轨道上,但是您正在混淆关系,就好像它是必需的规则一样。还要仔细研究如何使用点符号来处理 lop 级别的字段。阅读文档无疑是最好的建议。 :-) 顺便说一句,你的标记很乱。
        猜你喜欢
        • 2020-11-21
        • 1970-01-01
        • 1970-01-01
        • 2017-06-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多