目的

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

対応方針

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

対応方針(続き)

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

コード

具体的には

  • コメントどおりなのですが、具体的には。
  • utils/decorators.py に上記コードを記述
  • app/views.pyに下記記述(Ajaxリクエストでない場合はBadRequestを返す)
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
...

facebook slideshare rubygems github qiita