Обработка ошибок с помощью Python + Pylons - PullRequest
3 голосов
/ 26 марта 2010

Как правильно обрабатывать ошибки с помощью Python + Pylons?

Скажем, пользователь устанавливает пароль через форму, которая при передаче в класс модели через контроллер выдает ошибку, потому что она слишком короткая. Как обработать эту ошибку, чтобы на веб-странице отображалось сообщение об ошибке, а не весь сценарий, заканчивающийся страницей с ошибкой?

Должна ли быть какая-либо обработка ошибок в самом контроллере?

Надеюсь, я четко объясню.

Спасибо.

Ответы [ 3 ]

2 голосов
/ 26 марта 2010

Что вы используете для проверки ваших форм? Я использую формалхимия . Он проверяет входные данные с помощью встроенных и пользовательских валидаторов и передает список с найденными ошибками. Затем вы можете отобразить этот список любым способом в своем шаблоне.

Документация здесь .

1 голос
/ 27 марта 2010

Не претендуя на готовое решение, просто в качестве примера. На самом деле я скопировал большую часть кода декоратора из 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 голос
/ 26 марта 2010

Я использую formencode @validate decorator. Для него можно написать собственный валидатор, но проблема с обработкой исключений, возникающих в модели после проверки, все еще существует.

Вы можете написать декоратор с настраиваемыми действиями, похожий на тот, что используется в formencode, который будет обрабатывать исключения вашей модели и заполнять c.form_errors.

...