如何在架构中将 'excludes' 与 'default' 结合起来?

How is possible to combine 'excludes' with 'default' in schema?

field_1 默认必须为 0,但不允许与 field_2 一起使用。我的尝试:

from cerberus import Validator

schema = {
    'value_1': {
        'type': 'integer',
        'default': 0
    },
    'value_2': {
        'type': 'integer',
        'excludes': ['value_1', ]
    }
}
v = Validator(schema)

for doc in [{}, {'value_2': 1}, {'value_2': 1, 'value_2': 1}]:
    if not v.validate(doc, schema):
        print(v.errors)
    else:
        print(v.normalized(doc))

我得到了:

{'value_1': 0}
{'value_2': ["'value_1' must not be present with 'value_2'"]}
{'value_2': ["'value_1' must not be present with 'value_2'"]}

我想用规范化结果 {'value_1': 0, 'value_2': 1} 验证没有错误的第二个文档。我怎样才能达到预期的结果?

编辑 更清楚地解释我的目标:
- 如果传入文档中存在 value_1value_2,我想引发错误,但如果文档中不存在此键,则将 0 设置为 value_1
- 我想在 cerberus validation/normalization 过程中进行,并想通过更改验证模式或验证器

来解决它

这只是在了解您的要求后。这行得通。

from cerberus import Validator

schema = {
    'value_1': {
        'type': 'integer',
        'default': 0,
    },
    'value_2': {
        'type': 'integer',
        'excludes': ['value_1']
    }
}

v = Validator(schema)

for doc in [{}, {'value_2': 1}, {'value_2': 2, 'value_1': 3}]:
    print('Doc: {}'.format(doc))
    n_doc = {}
    if not v.validate(doc, schema):
        print('Error: {}'.format(v.errors))
        n_doc = v.normalized(doc)
        n_doc.update(v.normalized({}))
    else:
        n_doc = v.normalized(doc)
    print('Result: {}'.format(n_doc))

结果:

Doc: {}
Result: {'value_1': 0}
Doc: {'value_2': 1}
Error: {'value_2': ["'value_1' must not be present with 'value_2'"]}
Result: {'value_1': 0, 'value_2': 1}
Doc: {'value_1': 3, 'value_2': 2}
Error: {'value_2': ["'value_1' must not be present with 'value_2'"]}
Result: {'value_1': 0, 'value_2': 2}

快速回答 (TL;DR)

  • 验证和标准化总是可以分成不同的步骤

详细解答

上下文

  • python 2.7
  • cerberus 数据结构验证和规范化工具

问题

  • 场景:开发人员 ElRusoDevoWoze 希望将验证与数据规范化相结合,以便为缺失的字段提供默认值。

解决方案

  • 将数据验证与数据规范化分开

理由

  • 理由;;验证和规范化可以被认为是独立的过程
    • proc1;;区分不可接受的输入和可接受的输入
      • (垃圾vs宝)
      • (已验证与未验证)
      • (良构与非良构)
    • proc2;;优化可接受输入的内容

例子

  • 以下示例创建并应用两个模式
  • 一个模式提供默认值,另一个进行验证

    import pprint
    import yaml
    from cerberus import Validator
    pass
    
    schema_vali = yaml.safe_load('''
      value_1:
        type:       integer
        excludes:   value_2
        required:   True
      value_2:
        type:       integer
        excludes:   value_1
        required:   True
    ''')
    pass
    
    schema_norm = yaml.safe_load('''
      value_1:
        default:    0
    ''')
    pass
    
    sample_docs = yaml.safe_load('''
      ¯ {}                            ## doc0
      ¯ {'value_1': 1}                ## doc1
      ¯ {'value_2': 1}                ## doc2
      ¯ {'value_1': 1, 'value_2': 1}  ## doc3
      ''')
    pass
    
    vccvali = Validator(schema_vali)
    vccnorm = Validator(schema_norm)
    pass
    
    for ijj,doc in enumerate(sample_docs):
      if vccnorm.validate(doc):
        print("{ijj} NORM-YESS! -->".format(ijj=ijj)),
        print(vccnorm.normalized(doc))
        doc = vccnorm.normalized(doc)
      if not vccvali.validate(doc):
        print("{ijj} VALI-NOPE! -->".format(ijj=ijj)),
        print(vccvali.errors)
      else:
        print("{ijj} VALI-YESS! -->".format(ijj=ijj)),
        print(vccvali.normalized(doc))
        doc = vccnorm.normalized(doc)
    pass
    

输出结果

  0 NORM-YESS! --> {'value_1': 0}
  0 VALI-YESS! --> {'value_1': 0}
  1 NORM-YESS! --> {'value_1': 1}
  1 VALI-YESS! --> {'value_1': 1}
  2 VALI-YESS! --> {'value_2': 1}
  3 VALI-NOPE! --> {'value_1': ["'value_2' must not be present with 'value_1'"], 'value_2': ["'value_1' must not be present with 'value_2'"]}