代码之家  ›  专栏  ›  技术社区  ›  zlipp

cerberus:验证一个可选字段至少出现一次

  •  1
  • zlipp  · 技术社区  · 7 年前

    我用cerberus来验证数据。我的一个字段是可选的-不需要每个项目都有它。但是,必须在整个数据数组中至少填充一次密钥。

    例如,假设我想验证密钥 'c' 在我的数据列表中的至少一个词典中发生:

    from cerberus import Validator
    
    has_c = {'data': [{'a': 1, 'b': 2}, {'b': 2}, {'c': 3}]}
    no_c = {'data': [{'a': 1, 'b': 2}, {'a': 1}]}
    
    schema = {'data':
              {'type': 'list',
               'schema': {
                   'type': 'dict',
                   'schema': {
                       'a': {'required': True},
                       'b': {'required': True},
                       'c': {'required': False, 'at_least_one': True}
                   }
               }
               }
              }
    
    class MyValidator(Validator) # Some fancy code...
    ....
    
    v = MyValidator()
    
    v.validate(has_c, schema) # Passes
    v.validate(no_c, schema) # Fails
    

    这在cerberus之外似乎是可行的,但是如果可能的话,我想把这个方法保存在我的验证器中。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Flargebla    7 年前

    如果您希望方法位于验证器子类中,那么您将希望创建一个自定义规则,就像您所想的那样。

    from cerberus import Validator
    
    test_with_c = {'data': [{'a': 1, 'b': 2}, {'b': 2}, {'c': 3}]}
    test_with_no_c = {'data': [{'a': 1, 'b': 2}, {'a': 1}]}
    
    class MyValidator(Validator):
        def _validate_has_c(self, has_c, field, value):
            seen_c = False
            for v in value:
                if "c" in v:
                    seen_c = True
            if has_c and not seen_c:
                self._error(field, "Must contain a 'c' key")
    
    schema = {
        "data": {
            "type": "list",
            "has_c": True
        }
    }
    
    v = MyValidator(schema)
    
    print(v(test_with_c), v.errors)
    print(v(test_with_no_c), v.errors)
    

    运行此命令将产生与查找 c 输入其中一个元素。运行代码会产生

    True {}
    False {'data': ["Must contain a 'c' key"]}
    
    推荐文章