升级Eve与Cerberus版本后,嵌套字典验证触发"unknown rule"错误
生产服务器因为过时驱动宕机了,我一直在升级包来恢复服务。感觉快搞定了,但Eve这边出了点问题。我有下面的验证 schema,为了清晰删掉了一些字段;
survey.py
from . import question from . import building_data from . import address schema = { 'buildingAddress': { 'type': 'dict', 'schema': address.schema, }, 'surveyType': { 'type': 'string', 'allowed': [ "local", "global", ], }, 'questions': { 'type': 'list', 'schema': { 'type': 'dict', 'schema': question.embedded_schema, } }, }
questions.py
import copy schema = { 'name': { 'type': 'string', 'required': True }, 'type': { 'type': 'string', 'allowed': [ 'boolean', 'shortText', ], 'required': True, }, 'group': { 'type': 'string' }, 'title': { 'type': 'string', 'required': True }, 'oldCode': { 'type': 'string' }, 'questionSets': { 'type': 'list', 'schema': { 'type': 'string' }, }, 'min': { 'type': 'number', 'nullable': True, }, 'max': { 'type': 'number', 'nullable': True, }, 'range': { 'type': 'number', 'nullable': True, 'min': 1, }, 'minValue': { 'type': 'string', }, 'maxValue': { 'type': 'string', }, # single / multiple choice 'choices': { 'type': 'dict', 'propertyschema': { 'type': 'string', 'regex': '\d+' } }, } embedded_schema = copy.deepcopy(schema) embedded_schema.update( { '_id': { 'type': 'objectid', 'data_relation': { 'resource': 'questions', 'field': '_id', 'embeddable': False } }, } )
报错信息
发起POST请求时触发了SchemaError(self.schema_validator.errors)异常,错误主要来自"questions"字段,截取部分如下:
{'questions': [{'schema': ['no definitions validate', {'anyof definition 0': [{'schema': [{'_id': ['unknown rule'], '_version': ['unknown rule'], 'choices': ['unknown rule'], 'group': ['unknown rule'], 'maxValue': ['unknown rule'], 'minValue': ['unknown rule'], 'name': ['unknown rule'], 'oldCode': ['unknown rule'], 'questionSets': ['unknown rule'], 'range': ['unknown rule'], 'title': ['unknown rule'], 'type': ["must be of ['string', 'list'] type"]}], 'type': ['null value not allowed']}], 'anyof definition 1': [{'schema': ['no definitions validate', {'anyof definition 0': [{'choices': [{'propertyschema': ['unknown rule']}]}] ...
环境信息
- 当前版本:Eve 1.1.5,Cerberus 1.3.6
- 升级前版本:Eve 0.7.10,Cerberus 0.9.2
- 代码中未手动导入Cerberus,使用Eve自带的版本
解决方案
看起来你遇到的问题主要是Cerberus从0.9.x升级到1.x版本后的API变更,加上Eve和新版Cerberus的适配细节没跟上,我帮你梳理几个关键的修复点:
1. 替换propertyschema为valueschema
这是最直接触发报错的原因!Cerberus 1.x版本已经把字典类型的propertyschema参数重命名为valueschema了,你在questions.py的choices字段里还在用旧的参数名,这直接导致Cerberus识别为"unknown rule"。修改后的代码应该是:
'choices': { 'type': 'dict', 'valueschema': { 'type': 'string', 'regex': '\d+' } },
2. 确认Eve与Cerberus的版本兼容性
Eve 1.1.5的官方兼容范围是Cerberus 1.2.x到1.3.x,你用的1.3.6理论上符合要求,但如果修改上述问题后仍有报错,可以尝试降级到Cerberus 1.2.5(这个版本和Eve 1.1.x适配更稳定),看看是否能解决其他未知规则的问题。
3. 检查nullable规则的写法
虽然你当前的nullable: True写法在Cerberus 1.x里是支持的,但如果某些字段还是报错,可以尝试用anyof语法替代,比如把:
'min': { 'type': 'number', 'nullable': True, },
改成:
'min': { 'anyof': [ {'type': 'number'}, {'type': 'null'} ] },
这种写法在新版Cerberus里更明确,也能避免一些版本适配的小问题。
4. 验证Eve自定义规则的加载
报错里提到_id的data_relation是未知规则,这是Eve扩展的Cerberus规则,正常情况下Eve初始化时会自动注册这些规则。如果你的应用有自定义的Validator类,记得要继承eve.io.mongo.MongoValidator(或者对应数据库的Validator),确保Eve的规则被正确加载。
建议你先修改propertyschema这个最明确的问题,然后测试是否还存在报错,再逐步排查其他点。
备注:内容来源于stack exchange,提问作者Ozymandias

