Python: Поле принуждения Цербера, когда оно не пустое

#python #cerberus #coerce

Вопрос:

Я хотел бы, чтобы поле было пустым, но когда оно не пустое, я хочу, чтобы оно было целочисленным и проверялось по диапазону. Мне нужно будет принудить поле, если оно не пустое, к int, потому что оно вводится в виде строки. Есть ли способ сделать это? Мой подход приведен ниже, но, похоже, он не работает. Я провел кучу исследований, но еще не понял, как это сделать в том, что я нашел.

Образец:

 from cerberus import Validator

v = Validator()
v.schema = {
    'name': { 'type': 'string', 'minlength': 2},
    'age': {
        'oneof': [
            {'type': 'string', 'empty': True},
            {'type': 'integer', 'min': 5, 'max': 130, 'coerce': int, 'empty': False},
        ]
    }
}

if v.validate({'name': 'John', 'age': ''}):
    print('valid data')
else:
    print('invalid data')
    print(v.errors)
 

Я получаю ошибку при создании валидатора:

 Traceback (most recent call last):
  File "<stdin>", line 6, in <module>
  File "C:UserskenAppDataRoamingPythonPython36site-packagescerberusvalidator.py", line 562, in schema
    self._schema = DefinitionSchema(self, schema)
  File "C:UserskenAppDataRoamingPythonPython36site-packagescerberusschema.py", line 82, in __init__
    self.validate(schema)
  File "C:UserskenAppDataRoamingPythonPython36site-packagescerberusschema.py", line 262, in validate
    self._validate(schema)
  File "C:UserskenAppDataRoamingPythonPython36site-packagescerberusschema.py", line 278, in _validate
    raise SchemaError(self.schema_validator.errors)
cerberus.schema.SchemaError: {'age': [{'oneof': [{'coerce': ['unknown rule']}]}]}
 

Ответ №1:

У меня нет репутации, чтобы комментировать, и я знаю, что это не очень хороший ответ, но я не уверен, куда еще это поместить.

Причина, по которой вы получаете эту ошибку, заключается в том, что coerce это недопустимое правило в контексте oneof правила. Согласно документам, coerce считается правилом нормализации, и это не допускается ни в одном из *of правил.

Я знаю, что это не очень хорошее решение, но вы можете использовать правило check_with и написать пользовательскую функцию проверки. Затем в этой функции вы можете просто сбросить всю логику проверки, которая у вас там есть. Что-то вроде этого:

 def validate_age(f, v, e):
    # Perform your checks

my_schema = {
    "name": {
        "type": "string",
        "minlength": 2
    },
    "age": {
        "check_with": validate_age
    }
}