Djangoで1つのフォームに対して2つのボタンで処理を切り分ける方法

Djangoで1つのフォームに対して2つのボタンで処理を切り分ける方法をご紹介します。

以下の記事で作成したソースをベースにして、機能追加を行います。

DjangoでAjax処理を行う方法(GET/POST)

条件

  • Python 3.7.0
  • Django 2.2.3

urls.py

トップ画面に一覧画面を表示し、詳細画面を表示するという動作とします。
詳細画面でボタンクリックを行い、同画面でGET/POST結果の表示を行います。

from django.urls import path
from . import views

app_name = 'sample'

urlpatterns = [
    # トップ画面
    path('', views.IndexView.as_view(), name='index'),

    # 詳細画面
    path('sample/<int:pk>/', views.DetailView.as_view(), name='detail'),

    # Ajax処理
    path("sample/<int:pk>/exec/", views.exec_ajax, name='exec'),
    path("sample/<int:pk>/exec_another/", views.exec_another_ajax, name='exec_another'),
]

このソースでのポイントは、Ajax処理用のパス「sample/<int:pk>/exec/」および「sample/<int:pk>/exec_another/」を設定していることです。
詳細画面にてボタンが押された際、押されたボタンに応じて「sample/<int:pk>/exec/」または「sample/<int:pk>/exec_another/」にPOSTを行い、views.exec_ajaxで処理を実行します。

views.py

from django.http import HttpResponse
from django.views import generic
from .models import Location, WeatherData
import logging


logger = logging.getLogger('development')


class IndexView(generic.ListView):
    model = Location
    paginate_by = 5
    ordering = ['-updated_at']
    template_name = 'sample/index.html'


class DetailView(generic.DetailView):
    model = Location
    template_name = 'sample/detail.html'


def exec_ajax(request, pk):

    if request.method == 'GET':  # GETの処理
        param1 = request.GET.get("param1")  # GETパラメータ1
        param2 = request.GET.get("param2")  # GETパラメータ2
        param3 = request.GET.get("param3")  # GETパラメータ3
        logger.debug(param1 + param2 + param3)
        return HttpResponse(param1 + param2 + param3)

    elif request.method == 'POST':  # POSTの処理
        data1 = request.POST.get("input_data")  # POSTで渡された値
        logger.debug(data1)
        return HttpResponse(data1)


def exec_another_ajax(request, pk):

    if request.method == 'POST':  # POSTの処理
        data1 = request.POST.get("input_data")  # POSTで渡された値
        logger.debug(data1)
        return HttpResponse('ボタン2が押されました!')

exec_ajaxおよびexec_another_ajaxでは、詳細画面でボタンを押した際に実行されたPOSTの値を取得します。
exec_ajaxではPOSTの値をそのまま返す一方、exec_another_ajaxでは「ボタン2が押されました!」という文字列を返すようにしています。

テンプレート

detail.html(詳細画面)抜粋

<!-- POST(ボタン2つの処理切り分け) -->
<form id="form_button2" action="{% url 'sample:exec' object.pk %}" method="POST">
    {% csrf_token %}
    <input type="text" name="input_data" value="処理の切り分け">
    <button class="btn btn-success" type="submit" value="button1">ボタン1</button>
    <button class="btn btn-success" type="submit" value="button2">ボタン2</button>
</form>
<div id="resultPOSTbutton2"></div>


<script>

    $(function(){

        // フォームにtype="hidden"のinput要素を追加
        $('#form_button2').append('<input name="key" type="hidden" value="" />');

        // ボタンクリック時、type="hidden"のinput要素に自分の値を設定
        $("#button31, #button32").click(function(){
            $('input[name=key]').val($(this).val());
        });

        $('#form_button2').submit( function(event) {

            event.preventDefault();
            var form = $(this);

            // 押されたボタンによる切り分け
            var action_url = form.prop("action");
            if($('input[name=key]').val() == 'button2'){
                action_url = "{% url 'sample:exec_another' object.pk %}";
            }

            $.ajax({
                 url: action_url,
                 method: form.prop("method"),
                 data: form.serialize(),
                 timeout: 10000,
                 dataType: "text",
            })
            .done( function(data) {
                // 通信成功時の処理を記述
                $('#resultPOSTbutton2').text('POST処理成功:' + data);
            })
            .fail(function() {
                // 通信失敗時の処理を記述
                $('#resultPOSTbutton2').text('POST処理失敗.');
            })
        });
    });

</script>

ポイントは以下の通りです。

  • 対象のフォームにtype=”hidden”のinput要素を追加する。
  • ボタン1(id=”button31″)または、ボタン2(id=”button32″)がクリックされた際、対象ボタンのvalue値をフォームのtype=”hidden”のinput要素に設定する。
  • 対象のフォームがsubmitされた際、type=”hidden”のinput要素を取得して、押されたボタンを識別する。
  • 押されたボタンに応じて、urlを変更する。

実行結果

以下のように、押されたボタンに応じて処理を切り分けることが出来ます。

ボタン1(id=”button31″)が押された場合

フォームの値をそのまま表示します。

ボタン2(id=”button32″)が押された場合

「ボタン2が押されました!」という文言を表示します。

サンプルソース

GitHubにサンプルソースを公開しています。

https://github.com/kzmrt/ajax

参考

小粋空間:複数のsubmitボタンをonsubmitで判定する(jQuery)

http://www.koikikukan.com/archives/2018/11/29-000300.php

Qiita:<input type=submit>は止めて<button type=submit>を使うべき

https://qiita.com/irxground/items/c8537d30e9760c5b3e5c

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です