Как сделать требуемое правило Цербера зависит от условия

У меня есть большой документ json, в котором некоторые поля должны быть обязательными, если другие поля имеют точные значения. Например.

document = {'is_realty_address': False, 'postcode': 111111}

почтовый индекс должен быть обязательным, если is_realty_address == False. Все правила (кроме обязательных) применяются к полям, которые существуют в документе, поэтому мои пользовательские правила молчат, когда я

document = {'is_realty_address': False}

of-rules не поможет в моем случае, потому что у меня много «условно-обязательных» полей, которые зависят от множества разных полей. Итак, оф-правил сильно усложнит мою схему. Зависимости тоже не работают. Я пытался:

{'postcode': {'dependencies': {'is_realty_address': False}, 'required': True}}

Это возвращает ошибку, если почтовый индекс не отображается в документе, независимо от того, какое значение имеет is_realty_address.

v = Validator()
print(v.validate({'is_realty_address': False}, schema))
print(v.errors)

print(v.validate({'is_realty_address': True}, schema))
print(v.errors)

этот код возвращает:

False
{'postcode': ['required field']}
False
{'postcode': ['required field']}

Я также попытался реализовать метод проверки:

def _validate_conditional_required(self, conditional_required, field, value):
    """
    :param conditional_required:
    :param field:
    :param value:
    :return:
    The rule's arguments are validated against this schema:
    {'type': 'dict'}
    """
    for conditional_field, conditional_value in conditional_required.items():
        if self.document[conditional_field] == conditional_value and field not in self.document:
            self._error(field, errors.REQUIRED_FIELD)

со схемой

schema = {
    'is_realty_address': {'required': True, 'type': 'boolean'},
    'postcode': {'conditional_required': {'is_realty_address': False}},
}

но это правило не работает, если в документе нет «почтового индекса».

Есть ли способ установить правило «условно-обязательное»? Я хочу увидеть этот код:

schema = {
    'is_realty_address': {'required': True, 'type': 'boolean'},
    'postcode': {'conditional_required': {'is_realty_address': False}},
}
v = Validator()
print(v.validate({'is_realty_address': False}, schema))
print(v.errors)

print(v.validate({'is_realty_address': True}, schema))
print(v.errors)

возвращает:

True

False
{'postcode': ['required field']}

person Dmitry Bozhenko    schedule 14.02.2018    source источник


Ответы (1)


Я понял, что мою проблему можно решить комбинацией правил «исключает» и «один из»

schema = {
'is_realty_address': {
    'required': True, 'type': 'boolean',
    'oneof': [{'excludes': 'postcode', 'allowed': [False]}, {'allowed': [True]}]
},
'postcode': {'type': 'integer', 'required': True}}
v = Validator()
print(v.validate({'is_realty_address': True}, schema))
print(v.errors)

print(v.validate({'is_realty_address': False, 'postcode': 111111}, schema))
print(v.errors)

Этот код возвращает:

False
{'postcode': ['required field']}
False
{'is_realty_address': [{'oneof': ['none or more than one rule validate', {'oneof definition 1': ['unallowed value False'], 'oneof definition 0': ["'postcode' must not be present with 'is_realty_address'"]}]}]}

Так что в этом варианте схема не будет сильно усложняться.

person Dmitry Bozhenko    schedule 15.02.2018
comment
Вы должны изменить на: schema = { 'is_realty_address': { 'required': True, 'type': 'boolean', 'oneof': [{'excludes': 'postcode', 'allowed': [False]}, {'dependencies': 'postcode', 'allowed': [True]}] }, 'postcode': {'type': 'integer'}} - person BeGood; 29.11.2019