Djangoで定期的なAjax処理(POST)を行う方法
Djangoで定期的なAjax処理(POST)を行う方法をご紹介します。
ここでは、フォームの入力値を指定した間隔で自動POSTを行います。
目次
条件
- Django 3.0.7
- Python 3.7.0
models.py
models.pyに以下のようにPostクラスを追加します。
from django.db import models
class Post(models.Model):
"""投稿モデル"""
class Meta:
db_table = 'post'
title = models.CharField(verbose_name='タイトル', max_length=10)
comment = models.CharField(verbose_name='コメント', max_length=100)
created_at = models.DateTimeField(verbose_name='登録日時', auto_now_add=True)
updated_at = models.DateTimeField(verbose_name='更新日時', auto_now=True)
def __str__(self):
return self.title + ',' + self.comment
urls.py
トップ画面にフォーム画面を表示します。
また、Ajax処理用のURLを設定します。
from django.urls import path
from . import views
app_name = 'sampleApp'
urlpatterns = [
# トップ画面
path('', views.TestView.as_view(), name='index'),
# Ajax処理
path("exec/", views.exec_ajax, name='exec'),
]
forms.py
「forms.Form」のTestFormクラスを定義します。
from django.forms import forms, CharField
from sampleApp.models import Post
class TestForm(forms.Form):
title = CharField(
initial='',
label='タイトル',
max_length=10,
required=True, # 必須
)
comment = CharField(
initial='',
label='コメント',
max_length=100,
required=True, # 必須
)
def save(self):
# save data using the self.cleaned_data dictionary
data = self.cleaned_data
post = Post(title=data['title'], comment=data['comment'])
post.save()
views.py
フォームの処理には「FormView」を用います。
また、Ajax用のメソッドを定義して、POSTで送られてきたパラメータを取得し、何らかの処理を記述します。
from django.contrib import messages
from django.http import HttpResponse, QueryDict
from django.views.generic.edit import FormView
from sampleApp.forms import TestForm
class TestView(FormView):
template_name = 'sampleApp/index.html'
form_class = TestForm
success_url = '/' # リダイレクト先URL
def form_valid(self, form):
form.save() # 保存処理など
messages.add_message(self.request, messages.SUCCESS, '登録しました!') # メッセージ出力
return super().form_valid(form)
def exec_ajax(request):
if request.method == 'POST': # POSTの処理
# JSON文字列の取得
dic = QueryDict(request.body, encoding='utf-8')
title = dic.get('title')
comment = dic.get('comment')
# TODO:何らかの処理を実行する
if not title and not comment: # 入力値が空の場合
message = '何もしません。'
else: # 何か入力されている場合
# TODO:自動保存処理(DBの値と異なっていた場合、保存する。)
message = '自動保存しました。' + 'タイトル:' + title + ', コメント:' + comment
return HttpResponse(message)
テンプレート
index.htmlに、「メッセージ」と「フォーム」を表示するようにします。
また、jqueryを用いて定期的にAjaxのPOST処理が行われるようにします。
クロスサイトリクエストフォージェリ (CSRF) 対策のため、CSRFトークンの取得を行っています。
{% extends 'base.html' %}
{% block content %}
<h2>フォームサンプル</h2>
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
<form method="post" id="form01" >{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="送信">
</form>
<div id="resultPOST"></div>
<script>
// csrf_tokenの取得
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$(function() {
var POLLING_INTERVAL_TIME_IN_MILLIS = 10000; // 実行インターバル(ミリ秒)
(function polling() {
AutoSubmit();
window.setTimeout(polling, POLLING_INTERVAL_TIME_IN_MILLIS);
}());
function AutoSubmit() {
var val_title = $('#form01 [name=title]').val();
var val_comment = $('#form01 [name=comment]').val();
if(val_title && val_comment){ // フォームに入力されている場合
$.ajax({
type : "POST",
url : "{% url 'sampleApp:exec' %}",
data: {
"title": val_title,
"comment": val_comment,
},
contentType: "application/json",
timeout: 5000,
// AJAXリクエストにトークンをセット
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", getCookie("csrftoken"));
}
},
}).done(function(data) {
// alert("success");
$('#resultPOST').text('自動POST処理成功:' + data);
}).fail(function(jqXHR, textStatus) {
// #alert("error");
$('#resultPOST').text('自動POST処理失敗:');
});
}
}
});
</script>
{% endblock %}
実行結果
フォームが未入力の場合
自動POST処理は行われません。
フォームに入力済の場合
自動POST処理が行われます。(送信ボタンを押さなくてもPOSTが行われます。)
index.htmlの「POLLING_INTERVAL_TIME_IN_MILLIS」で設定した間隔で、定期的に実行されます。
参考
Django:クロスサイトリクエストフォージェリ (CSRF) 対策
https://docs.djangoproject.com/ja/3.0/ref/csrf/




