LoginSignup
4
5

More than 5 years have passed since last update.

Ajaxアクセスでなければエラーを返すdecorator

Last updated at Posted at 2016-06-09

目的

  • Ajaxリクエスト用のアクションなので、Ajaxリクエストの場合のみレスポンスしたい。
  • たとえば、WebブラウザからURL直接アクセスされたり、curlとかでスクレイピングされた場合はレスポンスを返したくない。

対応方針

  • AjaxはすなわちJavaScriptでの通信で、XMLHTTPRequest(XHR)という約束事に沿って実行されます。
  • この際にリクエストヘッダに X-Requested-With ヘッダがセットされます。
  • jQueryなどでは(おそらくセキュリティ的な理由から)クロスドメインアクセスの場合はこのヘッダがセットされなかったりします。
  • 判定方法としては、"リクエストヘッダにX-Requested-WithがあればAjax、なければ非Ajax"とします。

対応方針(続き)

  • Djangoにはこの判定メソッドが備わっています。 (see:HttpRequest.is_ajax)
  • リクエストがAjaxだったらJSON、そうでなければhtmlを返すような場合はそれぞれ判定すれば良さそうです。
  • ただ、今回はAjaxリクエストでなければエラーにしたいので、デコレーターにしてみます。

コード

utils/decorators.py
def ajax_required(ret_unexcepted):
    """
    Decorator for determing whether the request is Ajax, in Django-views.
    e.g.) in views.py
    from django.http import HttpResponseBadRequest
    from utils.decorators import ajax_required

    @ajax_requirxed(HttpResponseBadRequest())
    def index(request):
        pass
    """
    def _ajax_required(func):
        def wrapper(request, *args, **kwargs):
            if not request.is_ajax():
                return ret_unexcepted
            return func(request, *args, **kwargs)
        return wrapper
    return _ajax_required

具体的には

  • コメントどおりなのですが、具体的には。

  • utils/decorators.py に上記コードを記述

  • app/views.pyに下記記述(Ajaxリクエストでない場合はBadRequestを返す)

app/views.py
from django.http import HttpResponseBadRequest
from utils.decorators import ajax_required

@ajax_required(HttpResponseBadRequest())
def index(request):
    # any code

確認

  • 対応前(正常にレスポンスしている)
 $ curl --head http://localhost:5000/app/index/
 HTTP/1.1 200 OK
 ...
  • @ajax_required記述後(エラーレスポンスに変化している)
 $ curl --head http://localhost:5000/app/index/
 HTTP/1.1 400 Bad Request
 ...
4
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5