Django Ajaxで非同期通信

 

{{DZ_TITLE}}

Ajaxで非同期通信の方法をまとめました。
ページを遷移しないで、データをサーバーに渡したり、受け取ったりという事ができます。
Google mapなんてこの技術の塊ですね。

初めに

下記の内容をベースに作業を進めていきます。
この記事の前に、こちらを参照していただけると助かります。
Django テンプレート 使用 #1
Django テンプレート 使用 #1

  • pollsやmysiteという用語が出てきます。
    Django本家のチュートリアルでのサイト名、アプリケーションです。
    ご自身のお使いの値に変更してください。
    – mysite : サイト名
    – polls : アプリケーション名

URLの定義

polls/urls.py

from django.urls import path

from . import views

app_name = 'polls'
urlpatterns = [
    path('receive_from_js/', views.receive_from_js, name='receive_from_js'),
    path('', views.index, name='index'),
]

JavaScriptからデータを受けるので、受けるためのURLを定義します。
下記の1行を追加しました。

path('receive_from_js/', views.receive_from_js, name='receive_from_js'),

viewsの定義

polls/views.py

from django.http import HttpResponse
from django.template import loader

from django.http import QueryDict
import json

def index(request):
    template = loader.get_template('polls/index.html')
    context = {}
    return HttpResponse(template.render(context, request))

def test_data():
    from datetime import datetime as dt
    return dt.strftime(dt.now(),'%Y/%m/%d %H:%M:%S')

def receive_from_js(request):
    print('===== receive_from_js')
    if request.method == 'POST':
        dic = QueryDict(request.body, encoding='utf-8')
        test_data_from_js = dic.get('test_data_from_js')
        print('test_data_from_js : ',test_data_from_js)

        ret = json.dumps({'test_data_from_python' : test_data()})
        return HttpResponse(ret, content_type='application/json')
    else:
        ret = {}
        return HttpResponse(ret, content_type='application/json')

QueryDictとjsonを読み込みます。

  • QueryDict : JavaScriptから受け取ったデータを読み込む目的
  • json : データをJson形式にして、JavaScriptへ返す準備をする目的
from django.http import QueryDict
import json

JavaScriptから受け取ったデータを処理する関数。
Post型の受け取り側に処理を記載してください。

def receive_from_js(request):
    print('===== receive_from_js')
    if request.method == 'POST':
        dic = QueryDict(request.body, encoding='utf-8')
        test_data_from_js = dic.get('test_data_from_js')
        print('test_data_from_js : ',test_data_from_js)

        ret = json.dumps({'test_data_from_python' : test_data()})
        return HttpResponse(ret, content_type='application/json')
    else:
        ret = {}
        return HttpResponse(ret, content_type='application/json')

HTML側の記載

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  {% csrf_token %}
  <script src="https://code.jquery.com/jquery-3.3.1.js"> </script>
  <script type="text/javascript">

    function getCookie(name) {
      var cookieValue = null;
      if (document.cookie && document.cookie !== '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length ; i++) {
          var cookie = jQuery.trim(cookies[i]);
          // Does this cookie string begin with the name we want?
          if (cookie.substring(0, name.length + 1) === (name + '=')) {
            cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
            break;
          }
        }
      }
      return cookieValue;
    }

    function csrfSafeMethod(method) {
      // these HTTP methods do not require CSRF protection
      return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
    }

    $(document).on("click", "input.btn", function() {

      var csrf_token = getCookie("csrftoken");

      $.ajax({
           type: "POST",
           url: "/polls/receive_from_js/",
           data: {
               "test_data_from_js": 'flt_height',
             },
             contentType: "application/json",
             beforeSend: function(xhr, settings) {
                  if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                      xhr.setRequestHeader("X-CSRFToken", csrf_token);
                  }
          },
          success: function(data) {
            $('div.result').text(data['test_data_from_python']);
          },
          error: function(xhr, status, error) {
              alert(status + "\n" +
                "Status: " + xhr.status + "\n" + error);
          }
      });
    });
  </script>
</head>
<body>
  <input type="button" value="test" class='btn'>
  <div class='result'/>
</body>
</html>

ボタンを押したら、AjaxでデータをPython側に送って、受け取ります。
ボタンの定義と、結果は下記に入ります。

<input type="button" value="test" class='btn'>
<div class='result'/>

JQueryが無くても同様の事ができますが、こちらを使う方がよりシンプルに書けます。
なので、今回はJQueryを使います。

<script src="https://code.jquery.com/jquery-3.3.1.js"> </script>

セキュリティー関連でクロスサイトスクリプティング対策をするための定義です。
Ajaxに限らず、Formの受け取りなどで同じ定義が必要です。

{% csrf_token %}

おまじないの関数群です。
セキュリティー関連でクロスサイトスクリプティング対策をするために使う関数の定義です。

function getCookie(name) {
  var cookieValue = null;
  if (document.cookie && document.cookie !== '') {
    var cookies = document.cookie.split(';');
    for (var i = 0; i < cookies.length; i++) {
      var cookie = jQuery.trim(cookies[i]);
      // Does this cookie string begin with the name we want?
      if (cookie.substring(0, name.length + 1) === (name + '=')) {
        cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
        break;
      }
    }
  }
  return cookieValue;
}

function csrfSafeMethod(method) {
  // these HTTP methods do not require CSRF protection
  return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}

ajaxを実施している本体です。
var csrf_token = getCookie(“csrftoken”);
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader(“X-CSRFToken”, csrf_token);
}
の部分がクロスサイトスクリプティング対策になります。

$(document).on("click", "input.btn", function() {

  var csrf_token = getCookie("csrftoken");

  $.ajax({
       type: "POST",
       url: "/polls/receive_from_js/",
       data: {
           "test_data_from_js": 'flt_height',
         },
         contentType: "application/json",
         beforeSend: function(xhr, settings) {
              if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                  xhr.setRequestHeader("X-CSRFToken", csrf_token);
              }
      },
      success: function(data) {
        $('div.result').text(data['test_data_from_python']);
      },
      error: function(xhr, status, error) {
          alert(status + "\n" +
            "Status: " + xhr.status + "\n" + error);
      }
  });

JavaScriptからPythonへの送信部分です。
必要に応じて置き換えてください。

url: "/polls/receive_from_js/",
       data: {
           "test_data_from_js": 'flt_height',
         },

Pythonから結果が戻ってきたときの処理をここに記載します。
今回は、div.resultのテキストを受け取った値で置き換えています。

success: function(data) {
  $('div.result').text(data['test_data_from_python']);
},

関連記事

Django 目次- Python
Django 目次 - Python

おすすめ記事

Django テンプレート 使用 #2 Staticファイルの使用
Django テンプレート 使用 #2 Staticファイルの使用
Django Adminのパスワードを忘れたら? - Python
Django Adminのパスワードを忘れたら? - Python
Django 目次 - Python
Django 目次 - Python
Django チーター#1 - Python
Django チーター#1 - Python
Cookieの使い方 / JavaScript
Cookieの使い方 / JavaScript
プログラムは独学が良いか、スクールが良いか?【無償カウンセリング、無料体験あり】
プログラムは独学が良いか、スクールが良いか?【無償カウンセリング、無料体験あり】
Supponsered

外部サイト ↓プログラムを学んでみたい場合、学習コースなどもおすすめです!

Title : Photo by Steve Johnson on Unsplash

Comments

comments powered by Disqus