Пользовательские валидаторы вложенных кодов в схеме
Я хочу вложить свои собственные валидаторы в мою схему, например:
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']
Как видите, для такого рода конфиденциальности существует лазейка, но большинство автоматических инструментов распознают, что вы пытаетесь сделать что-то личное.