Пользовательские валидаторы вложенных кодов в схеме

Я хочу вложить свои собственные валидаторы в мою схему, например:

MySchema(Schema):
    class MyValidator(validators.FancyValidator):
        def _to_python(self, value, state):
            ...
    class MyOtherValidator(validators.FancyValidator):
        def _to_python(self, value, state):
            ...

    field_foo = All(validators.NotEmpty(),
                    MyValidator())
    field_bar = All(validators.NotEmpty(),
                    MyOtherValidator())

Тем не менее, кажется, что MyValidator а также MyOtherValidator поля б / к это form_errors содержать:

{ 
  'MyValidator': 'Missing value',
  'MyOtherValidator': 'Missing value'
}

Если я их не вкладываю, они кажутся нормальными. Что мне не хватает?

2 ответа

Мой совет: вы должны переместить FancyValidator определения подкласса к глобальной области, либо (1) в том же модуле непосредственно перед определением Schema в котором они используются, или (2) в отдельном модуле для большего повторного использования. Если нет конкретной причины, по которой требуется вложение, несколько дополнительных имен классов в пространстве имен модуля не должны повредить.

Например:

from formencode import All, FancyValidator, Schema, validators

class MyValidator(FancyValidator):
    def _to_python(self, value, state):
        return value + '_foo'

class MyOtherValidator(FancyValidator):
    def _to_python(self, value, state):
        return value + '_bar'

class MySchema(Schema):
    field_foo = All(validators.NotEmpty(), MyValidator())
    field_bar = All(validators.NotEmpty(), MyOtherValidator())

print MySchema().to_python({'field_foo': 'x', 'field_bar': 'y'}, None)

Результат:

{'field_foo': 'x_foo', 'field_bar': 'y_bar'}

В Python все, что вы определяете в своем классе, является полем. Будь то статические переменные, переменные, установленные с помощью self, методы или классы. Если вы хотите "скрыть" классы или сделать их "менее общедоступными", как, вероятно, является правильной формулировкой в ​​словаре python, вы должны начинать их имена с __.

>>> dir(X())
['A', '_B', '_X__C', '__doc__', '__module__']
>>> class X:
...     class A: pass
...     class __B: pass
...     c = 0
...     __d = 1
... 
>>> dir(X())
['A', '_X__B', '_X__d', '__doc__', '__module__', 'c']

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

Другие вопросы по тегам