如何在Cerberus Schema中结合excludes与default实现字段校验归一化?
Alright, let's tackle your Cerberus schema problem head-on. You need two key behaviors: block documents that have both value_1 and value_2, and auto-set value_1 to 0 when it's missing. Plus, you want to understand how to combine excludes and default rules properly. Here's the breakdown:
Step 1: Build the Schema with Combined Rules
First, let's write the schema that meets both requirements. We'll use excludes to enforce mutual exclusivity and default to populate value_1 when it's absent:
from cerberus import Validator # Define the schema schema = { 'value_1': { 'type': 'integer', 'default': 0, # Auto-set to 0 if missing 'excludes': 'value_2' # Can't exist if value_2 is present }, 'value_2': { 'type': 'integer', 'excludes': 'value_1' # Can't exist if value_1 is present } }
Step 2: How It Works
Let's break down each rule's role:
excludesRule: This rule ensures that if one field exists in the input document, the other cannot. We add it to both fields to make the exclusivity bidirectional—so whethervalue_1orvalue_2is present first, the other gets blocked.defaultRule: Applied tovalue_1, this fills in the value0automatically only whenvalue_1is not present in the input. Since we're not markingvalue_1asrequired, this only triggers on missing fields.
Step 3: Test the Schema
Let's verify it works for your target scenarios:
Scenario 1: Input has only value_2 (your desired normalization case)
v = Validator(schema) input_doc = {'value_2': 1} if v.validate(input_doc): print(v.normalized(input_doc)) # Output: {'value_1': 0, 'value_2': 1} else: print(v.errors)
This gives exactly the normalized result you want—value_1 is auto-set to 0, and no validation errors are thrown.
Scenario 2: Input has both value_1 and value_2 (should trigger error)
input_doc = {'value_1': 5, 'value_2': 1} if v.validate(input_doc): print(v.normalized(input_doc)) else: print(v.errors) # Output: {'value_1': ['cannot be present with value_2'], 'value_2': ['cannot be present with value_1']}
As expected, Cerberus throws a validation error telling you the two fields can't coexist.
Key Notes on Combining excludes and default
- Order of Operations: Cerberus first checks validation rules (like
excludes) against the original input, then appliesdefaultvalues. This means fillingvalue_1viadefaultwon't trigger theexcludesrule, because the original input didn't havevalue_1—only the normalized output does, and validation already passed. - Bidirectional Exclusivity: Don't forget to add
excludesto both fields. If you only added it tovalue_1, the schema would blockvalue_2whenvalue_1exists, but allowvalue_1to be added viadefaulteven ifvalue_2is present (which isn't what you want). - Type Safety: We added
type: 'integer'to both fields to ensure inputs are valid numbers—adjust this if your use case allows other types.
内容的提问来源于stack exchange,提问作者El Ruso

