使用Python + Pylons的错误处理

3 投票
3 回答
755 浏览
提问于 2025-04-15 20:54

如何正确处理Python和Pylons中的错误?

假设用户通过一个表单设置密码,但当这个密码通过控制器传递给模型类时,因为密码太短而出现错误。我们应该如何处理这个错误,以便在网页上显示错误信息,而不是整个程序直接跳转到错误页面?

控制器本身是否应该进行错误处理?

我希望我能清楚地表达我的意思。

谢谢。

3 个回答

1

这段话并不是说这是一个可以直接用在生产环境的解决方案,只是一个示例而已。实际上,我大部分的装饰器代码都是从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'))

new.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()}
1

我在使用 formencode 的 @validate 装饰器。虽然可以为它写自定义的验证器,但在验证之后,如果模型出现异常的问题还是存在的。

你可以写一个类似于 formencode 的自定义动作装饰器,这样就能处理你的模型异常,并把错误信息填充到 c.form_errors 中。

2

你们用什么来验证表单呢?我在用 formalchemy。它会用内置的和自定义的验证器来检查输入的数据,并把找到的错误放在一个列表里。然后你可以在你的模板中以任何方式显示这个列表。

文档可以在 这里 找到。

撰写回答