Error handling with Python + Pylons

旧时模样 提交于 2019-12-10 22:11:26

问题


What is the proper way to handle errors with Python + Pylons?

Say a user sets a password via a form that, when passed to a model class via the controller, throws an error because it's too short. How should that error be handled so that an error message gets displayed on the web page rather than the entire script terminating to an error page?

Should there be any error handling in the controller itself?

I hope I am explaining myself clearly.

Thank you.


回答1:


What are you using to validate your forms? I'm using formalchemy. It validates the input data using built-in and custom validators, and feeds a list with the errors it finds. You can then display that list in any way you want in your template.

Documentation here.




回答2:


I use formencode @validate decorator. It is possible to write custom validator for it but the problem with handling exceptions that occur in the model after validation still exists.

You could write custom action decorator similar to formencode one which will handle your model exceptions and populate c.form_errors.




回答3:


Not pretending to be production-ready solution, just as an example. Actually I've copied most of decorator code from 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()}


来源:https://stackoverflow.com/questions/2526458/error-handling-with-python-pylons

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!