formencode 中嵌套自定义验证器的模式
我想在我的模式里嵌套自定义的验证器,像这样:
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 个回答
0
在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']
如你所见,这种隐私设置其实有个漏洞,但大多数自动工具会识别出你是在尝试让某些东西变得私密。
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'}