问题
field_1
must be 0 by default, but not allowed with field_2
. My try:
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))
I got:
{'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'"]}
I want to validate second document without errors with normalized result {'value_1': 0, 'value_2': 1}
. How can I achieve the desired result?
EDIT More clear explanation of my goals:
- I want to raise error if value_1
and value_2
exists in incoming document, but set 0
to value_1
if this key not exists in document.
- I want to do it inside cerberus validation/normalization procedure and want to solve it by changing validation schema or validator
回答1:
Quick Answer (TL;DR)
- validation and normalization can always be separated into distinct steps
Detailed Answer
Context
- python 2.7
- cerberus data-structure validation and normalization tool
Problem
- Scenario: Developer ElRusoDevoWoze wishes to combine validation with data normalization, in order to provide default values for missing fields.
Solution
- separate data validation from data normalization
Rationale
- rationale ;; validation and normalization can be thought of as separate processes
- proc1 ;; distinguish unacceptable inputs from acceptable inputs
- (garbage vs treasure)
- (authenticated vs unauthenticated)
- (well-formed vs non-well-formed)
- proc2 ;; optimize the content of acceptable inputs
- proc1 ;; distinguish unacceptable inputs from acceptable inputs
Example
- The following example creates and applies two schemas
One schema provides the default values, the other does the validation
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
Output result
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'"]}
回答2:
This is just upon understanding your requirement. And this works.
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))
Result:
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}
来源:https://stackoverflow.com/questions/49203204/how-is-possible-to-combine-excludes-with-default-in-schema