Djangoで1つのフォームに対して2つのボタンで処理を切り分ける方法
Djangoで1つのフォームに対して2つのボタンで処理を切り分ける方法をご紹介します。
以下の記事で作成したソースをベースにして、機能追加を行います。
目次
条件
- 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を変更する。
実行結果
以下のように、押されたボタンに応じて処理を切り分けることが出来ます。
フォームの値をそのまま表示します。
「ボタン2が押されました!」という文言を表示します。
サンプルソース
GitHubにサンプルソースを公開しています。
参考
小粋空間:複数のsubmitボタンをonsubmitで判定する(jQuery)
http://www.koikikukan.com/archives/2018/11/29-000300.php
https://qiita.com/irxground/items/c8537d30e9760c5b3e5c




