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

