Djangoajaxエラー応答のベストプラクティス

Source jquery python ajax django

Djangoプロジェクトのユーザーエクスペリエンスを向上させるためにajaxを使用しています。ここでの私の懸念は、ブラウザにエラーを適切に応答する方法です。私の知る限り、私は次のいずれかを行うことができます。
  • は、リクエストデータを1つずつ検証し、例外を1つずつ保護します。何か悪いことが起こった場合は、Http404またはその他の例外を発生させて、エラーが発生したことを明示的に通知します。または
  • は、例外処理なしでコードを記述し、それが機能すると想定します。何か悪いことが起こった場合、キャッチされなかった例外は内部サーバーエラーを引き起こしますが、それでもブラウザ
  • のエラーです

    Pythonの場合、「明示的は暗黙的よりも優れている」という哲学が実際に重要であるため、私にとっては、fisrtメソッドはよりオーソドックスに見えます。ただし、すべての種類の例外チェックが2番目のチェックから削除されるため、よりクリーンで、断片化が少なく、読みやすくなります。

    jQueryを使用してajaxリクエスト/レスポンスを処理していますが、どちらのメソッドも機能しているようです。私の質問は次のとおりです。
  • どちらの方法も使用できますか?
  • 2番目のメソッドは他のJavascriptライブラリでは失敗しますか?
  • これのベストプラクティスは何ですか?

  • PS。私は重要なデータ検証を行います。そのためのトピックを外さないでください。 :)
    推奨答え
    ステータスコードが4xxまたは5xxの応答を返す場合、これはエラーであり、jQuerieserrorハンドラーをトリガーします。毎回単純にステータス200を返し、JSON応答で「エラー」フィールドを使用することは確かに可能ですが(dm03514で提案されているように)、これは2つの理由で悪いです。
  • これはHTTPの適切な慣行に違反しています。
  • で定義されたエラーコードがたくさんあるのには理由があります
  • jQueryにエラーハンドラーがすでにあるという事実を使用することはできません。これにより、通常の動作をエラー処理から分離できます。

  • ほとんどの場合、エラー応答は非エラー応答とは大きく異なります。したがって、このメッセージの処理を1つのJSコードにまとめても意味がありません。したがって、要約すると、通常の応答にはステータス200のJSON応答を使用し、エラーには(適切な!)4xx / 5xx応答を返します。これらはJSONペイロードも伝送できるため、サーバー側でエラーに関する詳細を追加できます。
    その他答え #1
    私の考えでは:
  • 2番目の方法は受け入れられません。
  • サーバーは引き続きhttp応答を送信するため、失敗することはありません。
  • 私のプロジェクトで何をしているのか教えてください:

  • プロジェクトの開始時に、常にフォルダー構造の先頭にerrorsという名前のモジュールを事前に追加します。最初に、Exceptionから継承する基本のExceptionクラスを記述し、次に、経験からObjectNotFoundValidationErrorなどの一般的なExceptionクラスをいくつか書き出します。コードで例外を発生させる必要があると思う場合は、このモジュールの例外を使用し、新しい種類の例外を処理する必要がある場合は、新しい例外を記述します。

    次に、それらをどのように処理するかについての作業です。 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.5statusCodeの新機能を使用できます。
    $.ajax({
      statusCode: {
        404: function() {
          alert('page not found');
        }
      }
    });
    

    jqueryドキュメントから:

    A map of numeric HTTP codes and functions to be called when the response has the corresponding code. For example, the following will alert when the response status is a 404

    その他答え #2
    両方の方法が受け入れられるかどうかは答えられませんが、私が何をしているのかを伝えることしかできません。私の見解では、次のような特定の/明示的なエラーをキャッチします。
  • 投稿
  • のパラメータが無効または欠落しています
  • データベースにすでに存在するユーザー名などの高レベルのエラー(たとえば、サインアップ状況で)
  • 他のすべてのシステムエラー

  • エラーをユーザーが知っておく必要のある特定のエラーとして分類し、それ以外のすべてを分類すると、コードは最大で2つまたは3つのエラールートを返しますが、これはそれほど悪くはありません。
    私はJSONを使用してエラーを返しますが、私の構造は通常次のようなものです。
    respons={}
    response["error|ok"]
    response["msg"]="User not found"
    response["type"]=ERROR_TYPE # only applicable for errors
    

    明らかにこれは非常に基本的なことですが、うまくいけば一般的なアイデアが得られます。システムで生成された内部サーバーエラーをユーザーに表示させないことをお勧めします。これは、内部アプリの場合でも、ひどいユーザーエクスペリエンスです。

    お役に立てれば。
    その他答え #3
    私はあなたの提案されたアプローチのどちらも取りません。私はシドが言ったことに沿って何かを提案したいと思います。エラーのないコードを書きたくないのはなぜですか?

    私は常に、私が書いたコードで起こりうるすべてのバグとエラーに対処しようとします。これには、ユーザー入力の検証が含まれます。 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のコールバックで、ユーザーが間違ったことをユーザーに警告しない場合は、応答が有効であることを確認します。あなたが彼らのためにアプリを作っているので、彼らをぶら下げたままにしないでください!
    その他答え #4
    オプション1を使用しますが、完全に説明する方法ではありません。検証エラーが発生したことを応答コンテンツ(JSONまたはテキストを使用)に示すstatus_code 200のHttpResponseを返す必要があります。その後、JQueryを使用してクライアントで応答を処理します。応答の内容を確認し、検証エラーがあったかどうかを検出するだけです。

    HttpResponseのJSON文字列の例:
    {"errors": "true", "messages": ["Error #1", "Error #2", "etc."]}
    

    オプション2は、サーバーによってスローされ、通常はプログラマーに知られていないキャッチされない例外がある場合に内部サーバーエラーが発生するため、適切な方法ではありません。

    検証エラーを示すためにHTTPステータスコードを使用しないでください。これは目的ではありません。

    関連記事

    gitlabLDAPの設定-特別なgitlabユーザーなしの認証
    stackのルートアクティビティとして特定のアクティビティを作成します
    OperaでのJQuery.Validateの失敗
    Jacskonパーサー:認識されないトークン 'tieheT': 'null'、 'true'、または 'false'を予期していました
    hide()ラジオボタン*および* jqueryのテキストラベル