forms.pyを使って作ったフォームの入力内容をViewsで使う方法は分かる。
JavaScriptで計算した内容をAjaxでViewsに渡す方法も分かる。
でもフォームとJavaScriptの計算結果を同じボタンでViewsに渡す方法が分からない。。。
ということで、formの内容をJavaScriptで取得してまとめてAjaxで送るという方法をとったので記録します。
やりたいこと
この状態でStop&Submitボタンを押したら、modelsにTaskとDetailsとストップウォッチで測っている時間が登録され、画面下の表に追加される、という形にしたいです。
HTML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<form method="post" action="">{% csrf_token %} <table class="table"> <tbody> <tr> <th>Task</th> <td>{{ form.kind }}</td> </tr> <tr> <th>Details</th> <td>{{ form.detail }}</td> </tr> </tbody> </table> <div class="stopwatch_wrapper"> <div class="display"> <span id="hours" class="time">00</span> <span id="minutes" class="time">00</span> <span id="seconds" class="time">00</span> </div> <p> <button class="btn btn-primary" id="start">Start</button> <button class="btn btn-primary" id="stop">Stop&Summit</button> </p> </form> |
forms.pyを使っています。
普通ajaxを使う時には要素にidを付与しますが、Djangoのformsを使った場合は、、、Djangoが勝手にidを付与してくれるようです。
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
stop.addEventListener('click', () => { clearInterval(timer_id); start.innerHTML = 'restart'; press_stop_time = new Date().getTime(); past_moving_time += press_stop_time - press_start_time; console.log(past_moving_time/1000); var detail = $('#id_detail').val(); var kind_id = $('#id_kind').val(); console.log(detail); console.log(kind_id); var cookie = getCookie('csrftoken') if(kind_id != ""){ $.ajax({ url: '/status/', headers: {'X-CSRFToken': cookie}, type: 'POST', data: { 'miliseconds': past_moving_time, 'kind_id':kind_id, 'detail': detail, }, success: function(e){ console.log(e); }, error: function(e){ console.log(e); } }); } document.location.reload() |
ストップウォッチに関する部分は完全にこのサイトからいただきました。
コピペコピペで作った結果、Jqueryの記述とJavaScriptの記述が混ざっていますが、、、動くので良しとします。
formsを使った時にDjangoが付与してくれていたid、「id_detail」を指定してフォームに入力された内容を取得します。
1 |
var detail = $('#id_detail').val(); |
それをJavaScriptで作ったストップウォッチの時間と合わせてajaxで送信しています。
ajaxはformと違ってリロードせずに値を渡すことができますが、今回はSubmitした結果をmodelsに登録して、すぐに画面上の表に反映させたいので、あえてリロードさせています。
1 |
document.location.reload() |
views.py
1 2 3 4 5 6 7 8 9 10 11 12 13 |
if request.method=="POST": miliseconds=request.POST.getlist('miliseconds') kind_id=request.POST.getlist('kind_id') detail=request.POST.getlist('detail') if len(miliseconds)>0: hours=int(miliseconds[0])/1000/60/60 task = Task( task_kind=get_object_or_404(TaskKind, id=kind_id[0]), detail=detail[0], hours=hours, ) task.save() return redirect('index') |
ajaxでPOSTされたデータは、
1 |
request.POST.getlist('miliseconds') |
で取得できます。
あとはmodels.pyで定義したTask()に保存するだけ。
非同期通信がしたいわけではないので、ajaxを使わずに普通にPOSTする方法もあるんじゃないかと思いました。
JavaScriptからデータ送信するならajax、というイメージがあって今回はこれだけにしてしまいましたが、、、