2010-03-26 57 views
3

用Python + Pylons处理错误的正确方法是什么?用Python + Pylons处理错误

说一个用户通过一个窗体设置密码,当通过控制器传递给模型类时,由于窗体太短而引发错误。应如何处理该错误,以便在网页上显示错误消息而不是整个脚本终止于错误页面?

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

我希望我清楚地解释自己。

谢谢。

回答

2

你用什么来验证你的表格?我正在使用formalchemy。它使用内置的和自定义的验证器来验证输入数据,并为列表提供找到的错误。然后,您可以以任何您想要的方式在模板中显示该列表。

文档here

1

我使用formencode @validate装饰器。可以为其编写自定义验证程序,但处理验证后模型中发生的异常问题仍然存在。

您可以编写类似于formencode的自定义操作装饰器,它将处理您的模型异常并填充c.form_errors。

+0

你碰巧有任何示例代码,您可以包括以说明如何做到这一点?谢谢! – ensnare 2010-03-26 22:03:26

+0

我在单独的答案中添加了代码示例 – Yaroslav 2010-03-26 23:44:39

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()}