<p>签出flatland代码(<code>hg clone http://bitbucket.org/jek/flatland</code>)是很有用的,因为文档和示例还没有完全到位。在</p>
<p><code>Form</code>从<code>Dict</code>继承,后者从<code>Container</code>继承,后者从{<cd5>}继承。有两个类元素可以帮助:</p>
<ul>
<li><code>descent_validators</code>(from<code>Container</code>)-在下降(第一)阶段运行的一个iterable验证器。在</li>
<li><code>validators</code>(from<code>Element</code>)-在上升(第二)阶段运行的一个iterable验证器。在</li>
</ul>
<p>为了获得我想要的行为(仅当用户名和密码有效时才检查account),我需要将我的验证器添加到<code>validators</code>类变量中,并检查子验证器是否通过。在</p>
<p>我的代码现在看起来像这样:</p>
<pre><code>class CheckCredentials(Validator):
'''Checks credentials and creates an account object'''
def validate(self, element, state):
username = element['username']
password = element['password']
if not (username.all_valid and password.all_valid):
return false
self.account = Account(username.u, password.u)
return self.account.valid()
class doSomethingForm(Form):
'''Do an action with account credentials'''
username = String.using(default='',
validators=[Present(), UsernameFormat()])
password = String.using(default='',
validators=[Present(), PasswordFormat()])
action = String.using(default='',
validators=[Present(), ActionFormat()])
validators = (CheckCredentials(),)
@expose('/do_something')
def doSomething(request):
form = doSomethingForm.from_defaults()
form.set_flat(request.form)
result_html = ''
method = request.method
if method == 'POST' and not form.validate():
method = 'GET'
errors = []
if form.errors: errors.extend(form.errors)
for el in form.all_children:
if el.errors: errors.extend(el.errors)
result_html = errorsToHtml(errors)
if method == 'POST':
result_html = form.account.action(form['action'].u)
return render_template('do_something.html',
result=result_html, **form.value)
</code></pre>
<p>我认为flatland可以做一些更酷的事情来帮助生成HTML表单,但是到目前为止,我对此非常满意。在</p>
<p>感谢<a href="https://stackoverflow.com/users/54017/wolph">WoLpH</a>和{a2}的帮助。在</p>