Лучшая практика реагирования на ошибки Django Ajax - PullRequest
11 голосов
/ 21 марта 2012

Я использую ajax для улучшения взаимодействия с пользователем в моем проекте Django.Меня беспокоит, как правильно отреагировать на ошибку браузера.Насколько я знаю, я могу либо:

  1. проверять данные запроса по частям и охранять исключение один за другим.Если происходит что-то плохое, вызовите Http404 или другое исключение, чтобы явно объявить об ошибке.Или
  2. просто напишите код без обработки исключений и предположите, что он будет работать.Если случится что-то плохое, необработанное исключение вызовет внутреннюю ошибку сервера, которая все еще является ошибкой для браузера

Для меня метод fisrt кажется более ортодоксальным, как в Python философия «Explicitлучше, чем неявное "действительно рассчитывает.Но так как все виды проверки исключений удалены из второй, она более чистая, менее фрагментированная и более читаемая.

Я использую jQuery для обработки запроса / ответа ajax, и оба метода работают.Мои вопросы:

  1. Приемлемы ли оба метода?
  2. Сбоит ли второй метод для других библиотек Javascript?
  3. Каков наилучший способ для этого?

PS.Я делаю проверку важных данных.Пожалуйста, не забивайте тему для этого.:)

Ответы [ 5 ]

17 голосов
/ 21 марта 2012

Если вы возвращаете ответ с кодом состояния 4xx или 5xx, это ошибка и вызовет обработчик jQueries error.Хотя, конечно, можно каждый раз просто возвращать статус 200 и использовать поле «ошибка» в ответе JSON (как предложено dm03514), это плохо по двум причинам:

  1. Это нарушаетхорошая практика HTTP.Существует причина , почему определено множество кодов ошибок

  2. Вы не можете использовать тот факт, что jQuery уже имеет обработчик ошибок, который позволяет вам отделитьнормальное поведение от обработки ошибок.

В большинстве случаев ответ об ошибке будет сильно отличаться от ответа без ошибок, поэтому просто не имеет смысла помещать обработку этих сообщений в одинкусок кода JS.Итак, чтобы подвести итог, используйте ответ JSON со статусом 200 для ваших обычных ответов и верните (соответствующий!) Ответ 4xx / 5xx для ошибок.Они также могут нести полезную нагрузку JSON, поэтому ваша серверная часть может добавить дополнительные сведения об ошибке.

2 голосов
/ 21 марта 2012

По моему мнению:

  1. второй метод неприемлем.
  2. он не потерпит неудачу, поскольку сервер все равно отправит ответ http.
  3. Пустья расскажу вам, что я делаю в своих проектах:

когда мой проект запускается, я всегда предварительно добавляю модуль с именем errors в начало структуры папок, во-первых, я напишу базовый класс Exceptionкоторый наследует от Exception, а затем выписать некоторые общие классы исключений, такие как ObjectNotFound, ValidationError из моего опыта.Когда я думаю, что в моем коде должно возникнуть исключение, я буду использовать исключения из этого модуля, и когда я обнаружу, что необходимо обработать исключение нового типа, я напишу в нем новое исключение.

Тогда эторабота для того, как справиться с ними.Поскольку вы используете Django, очень просто перехватывать исключения через промежуточное ПО, вы можете написать что-то вроде этого:

from youproject import errors

# categorize your exceptions
400_ERRORS = (errors.ValidationError, errors.ParametersMissing, )
403_ERRORS = (errors.AuthenticationError, )
404_ERRORS = (errors.ObjectNotFound, errors.ResourceNotExist, )

class ExceptionHandleMiddleware(object):
    def process_exception(self, request, e):
        # set status_code by category of the exception you caught
        if isinstance(e, 400_ERRORS):
            status_code = 400
        elif isinstance(e, 403_ERRORS):
            status_code = 403
        elif isinstance(e, 404_ERRORS):
            status_code = 404
        else:
            # if the exception not belone to any one you expected,
            # or you just want the response to be 500
            status_code = 500
            # you can do something like write an error log or send report mail here
            logging.error(e)

        response_dict = {
            'status': 'error',
            # the format of error message determined by you base exception class
            'msg': str(e)
        }
        if settings.debug:
            # you can even get the traceback infomation when you are in debug mode
            response_dict['traceback'] = traceback.format_exc()

        # set header and return the response
        ....

Приведенный выше код представляет собой сводку о том, как я обрабатываю исключения в моих проектах, в целом.речь идет о точном контроле исключений, правильной категоризации исключений и, конечно, философии «явное лучше, чем неявное».

=== ОБНОВЛЕНИЕ === Когда речь идет о том, как обращаться с соответствующими ответами в ajax,Вы можете использовать новую функцию в jquery1.5 statusCode:

$.ajax({
  statusCode: {
    404: function() {
      alert('page not found');
    }
  }
});

из документации jquery:

Карта числовых кодов HTTP и функций, вызываемых при ответеимеет соответствующий код.Например, следующее будет оповещать, когда статус ответа 404

0 голосов
/ 21 марта 2012

Я бы не стал использовать ни один из предложенных вами подходов. Я хотел бы предложить что-то вроде того, что сказал Сид. Почему вы не хотите писать безошибочный код?

Я бы постарался устранить все возможные ошибки и ошибки в коде, который я пишу всегда. Это включает в себя проверку ввода пользователя. С ajax я думаю, что важно отправлять сообщения обратно пользователю. Это легко сделать с помощью JSON.

response_dict = {}
try:
   # do action that could cause an error
except ExpectedError as e:
   response_dict['success'] = False
   response_dict['message'] e.msg # or custom message
   return HttpResponse(json.dumps(repsonse_dict))

тогда при вашем обратном вызове ajax убедитесь, что ответ верен, если он не предупреждает пользователя о том, что он сделал неправильно. не оставляйте их в покое, вы создаете для них приложение!

0 голосов
/ 21 марта 2012

Используйте опцию 1, но не полностью так, как вы ее описали, вы должны вернуть HttpResponse со значением status_code 200, указывающим в содержании ответа (используя JSON или некоторый текст), что произошла ошибка проверки, а затем, когда вы обрабатываете ответ наклиент с JQuery просто проверяет содержимое ответа и обнаруживает, были ли ошибки проверки.

Пример строки JSON для HttpResponse:

{"errors": "true", "messages": ["Error #1", "Error #2", "etc."]}

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

Не используйте коды состояния HTTP для обозначения ошибок проверки, это не является их целью.

0 голосов
/ 21 марта 2012

Я не могу ответить, приемлемы ли оба метода, но могу только сказать вам, что я делаю. На мой взгляд, я ловлю некоторые конкретные / явные ошибки, такие как:

  • Неверные или отсутствующие параметры в посте
  • Ошибки высокого уровня, такие как имя пользователя, уже присутствующее в базе данных (например, при регистрации)
  • Все остальные системные ошибки

Я думаю, что если вы классифицируете свои ошибки как некоторые конкретные ошибки, о которых должен знать пользователь, а затем все остальное, то ваш код будет иметь максимум 2 или 3 возврата с маршрутами ошибок, что, по-моему, не так уж плохо. Я использую JSON для возврата ошибок, и моя структура обычно такая:

respons={}
response["error|ok"]
response["msg"]="User not found"
response["type"]=ERROR_TYPE # only applicable for errors

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

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...