似非プログラマのうんちく

「似非プログラマの覚え書き」出張版

巳年じゃないけど Python やろうぜ(その 19)

Ajax の活用

以前作成した customer_search アプリケーションを Ajax を活用して作り変えてみましょう。

Ajax 活用のための準備

Ajax 活用のために、いくつかの準備が必要です。

1. js.cookie.js をダウンロードする

GitHub - js-cookie/js-cookie: A simple, lightweight JavaScript API for handling browser cookies

上記サイトから js.cookie.js をダウンロードします。間違っても script 要素の src 属性に URL を直接打ち込まないように(GitHub は CDN ではありません !)。

持って来た js.cookie.js は django_test/customer_search/static/customer_search/js/ に保存します。

2. csrf_token.js の作成

以下の内容で django_test/customer_search/static/customer_search/js/ 内に csrf_token.js を作成します。ほぼ公式ドキュメントからのコピペです。

var csrftoken = Cookies.get('csrftoken');

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

$.ajaxSetup({
  beforeSend: function(xhr, settings) {
    if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
      xhr.setRequestHeader('X-CSRFToken', csrftoken);
    }
  }
});


3. Ajax のためのスクリプト作成

django_test/customer_search/static/customer_search/js/search.js

$('form').submit(function (event) {
  event.preventDefault();
  $.post(
    $('form').attr('action'),
    { 'customer_id': $('#id_customer_id').val() },
    function (res) {
      $('#id_customer_name').val(res.customer_name);
      $('#id_customer_phone').val(res.customer_phone);
    }
  );
});

かなり雑に書いてますがとりあえず。

4. テンプレート内でスクリプトを呼ぶ

{% load static i18n %}
{% trans 'customer search' as page_title %}
<!doctype html>
<html>
  <head>
    <title>{{ page_title | title }}</title>
    <link rel="stylesheet" href="{% static 'customer_search/css/search.css' %}">
    <script src="//code.jquery.com/jquery-3.2.1.min.js"></script>
    <script src="{% static 'customer_search/js/js.cookie.js' %}"></script>
    <script src="{% static 'customer_search/js/csrf_token.js' %}"></script>
  </head>
  <body>
    <h1>{{ page_title | title }}</h1>
    <form method="post" action="{% url 'customer_search:search' %}">
      <!-- form 内は変更しないので省略 -->
    </form>
    <script src="{% static 'customer_search/js/search.js' %}"></script>
  </body>
</html>

5. urls.py の修正

url 逆引きの設定も含めて書き換え。

from django.conf.urls import url
from . import views

app_name = 'customer_search'
urlpatterns = [
    url(r'^$', views.index, name='index'),
    url(r'^search/$', views.search_ajax, name='search'),
]

6. views.py の修正

from django.shortcuts import render
from django.http.response import JsonResponse
from django.utils.translation import ugettext as _
from .forms import CustomerForm
from .models import Customer

# Create your views here.


def index(request):
    form = CustomerForm(label_suffix='')
    return render(request, 'customer_search/search.html', {
        'form': form,
    })


def search_ajax(request):
    customer_id = request.POST['customer_id']
    try:
        customer = Customer.objects.get(pk=customer_id)
        data = {
            'customer_name': customer.name,
            'customer_phone': customer.phone,
        }
    except Customer.DoesNotExist:
        message = _('No data!')
        data = {
            'customer_name': message,
            'customer_phone': message,
        }
    return JsonResponse(data)

送りたいデータを辞書形式にして JsonResponse で送信するだけ。いろいろ調査しましたがこれが一番簡単のようです。

課題

フォームのバリデーションをどうするか。現状では不正な値を入力したときに特に何も起きない。