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