【发布时间】:2010-03-26 20:17:49
【问题描述】:
使用 Python + Pylons 处理错误的正确方法是什么?
假设用户通过表单设置密码,当通过控制器传递给模型类时,由于密码太短而引发错误。应该如何处理该错误,以便在网页上显示错误消息而不是整个脚本终止到错误页面?
控制器本身应该有任何错误处理吗?
我希望我能清楚地解释自己。
谢谢。
【问题讨论】:
标签: python error-handling pylons
使用 Python + Pylons 处理错误的正确方法是什么?
假设用户通过表单设置密码,当通过控制器传递给模型类时,由于密码太短而引发错误。应该如何处理该错误,以便在网页上显示错误消息而不是整个脚本终止到错误页面?
控制器本身应该有任何错误处理吗?
我希望我能清楚地解释自己。
谢谢。
【问题讨论】:
标签: python error-handling pylons
您使用什么来验证您的表单?我正在使用formalchemy。它使用内置和自定义验证器验证输入数据,并提供一个包含它发现的错误的列表。然后,您可以在模板中以任何您想要的方式显示该列表。
文档here。
【讨论】:
我使用formencode @validate 装饰器。可以为它编写自定义验证器,但是验证后模型中出现的异常处理问题仍然存在。
您可以编写类似于formencode one 的自定义操作装饰器,它将处理您的模型异常并填充c.form_errors。
【讨论】:
不假装是生产就绪的解决方案,只是作为一个例子。实际上我已经从 pylons.decorators 复制了大部分装饰器代码:
from decorator import decorator
from webob import UnicodeMultiDict
class ModelException(Exception):
pass
def handle_exceptions(form):
def wrapper(fn, self, *args,**kwargs):
try:
return fn(self, *args, **kwargs)
except ModelException, e:
errors = str(e)
params = request.POST
is_unicode_params = isinstance(params, UnicodeMultiDict)
params = params.mixed()
request.environ['pylons.routes_dict']['action'] = form
response = self._dispatch_call()
# XXX: Legacy WSGIResponse support
legacy_response = False
if hasattr(response, 'content'):
form_content = ''.join(response.content)
legacy_response = True
else:
form_content = response
response = self._py_object.response
# If the form_content is an exception response, return it
if hasattr(form_content, '_exception'):
return form_content
form_content = htmlfill.render(form_content, defaults=params,
errors=errors)
if legacy_response:
# Let the Controller merge the legacy response
response.content = form_content
return response
else:
return form_content
return decorator(wrapper)
class HelloFormSchema(Schema):
allow_extra_fields = True
filter_extra_fields = True
name = formencode.validators.UnicodeString(not_empty=True)
email = formencode.validators.UnicodeString(not_empty=True)
class HelloController(BaseController):
def new(self):
return render('/hello/new.html')
def view(self):
return 'created'
@handle_exceptions(form='new')
@validate(schema=HelloFormSchema(), form='new')
@restrict("POST")
def create(self):
#here is code interacting with model which potentially could raise exception:
if self.form_result['name'] == 'doe':
raise ModelException('user already exists!')
return redirect(url(controller='hello', action='view'))
新的.html:
${h.form(h.url(controller='hello', action='create'), 'post')}
<dl>
<dt>Name</dt>
<dd>${h.text('name')}</dd>
<dt>Email</dt>
<dd>${h.text('email')}</dd>
<dd>
${h.submit('create', 'Create')}
</dd>
</dl>
${h.end_form()}
【讨论】: