銀月の符号

Python 使い見習いの日記・雑記

Django と JQuery でフォームの処理

JavaScript 再入門から1週間弱。 JQuery で遊べるところまできた。あるフォームの内容を非同期通信するページを DjangoJQuery を用いて作成する手順について自分なりに整理してみる。 Ajax

フォーム

Django でフォームを扱う方法の一つである django.forms のマニュアルは http://djangoproject.jp/doc/ja/1.0/topics/forms/index.html にある。 Ajax が絡んでもやるべきことは特に変わらない。

なお、フォームクラスに、自身の表示に必要な javascript ファイルを覚えさせておくことができる。この機能を使う場合、『Form Media』を参考に Media クラスを定義する。すると、フォームインスタンスの media プロパティで head タグ内に挿入すべき script タグを出力できるようになる。

from django import forms

class SpamForm(forms.Form):
    spam = forms.CharField()
    
    class Media:
        js = ("js/jquery-1.3.2.min.js", "js/spam.js") 

テンプレートおよび JavaScript(JQuery)

Django テンプレートを用いてフォームを簡易生成するにはフォームインスタンスの as_p メソッドなどを使う。ただし form タグや送信ボタンは自動で生成されたりはしないので自前で追加することになる。この生成された HTML が気に入らなければ、細かい指示を出すこともできる。方法は前述のマニュアルを参照。

次に JavaScript(JQuery) でイベント関数を作成する。 Ajax 通信対象の URL は attr("action") として form タグの action 属性から得る。フォームに入力された内容は serialize で得られる。 HTTP 通信の種別は指定しなければ GET になる。 POST を使うならば type に "POST" と指定する。

作成できたら送信ボタンに対し、このイベントを登録する。

<form id="spam_form" action="{% url spam-spam %}" method="POST">
{{ spam_form.as_p }}
<input id="spam_button"  type="button" value="送信">
</form>
SPAM = {}

SPAM.spam = function() {
    $.ajax({
            "url": $("form#spam_form").attr("action"),
            "type": "POST",
            "data": $("form#spam_form").serialize(),
            "dataType": "json", // ビューが返すデータの種類を指定
            "success": function(json){
                // 送受信完了した際の処理をここに記述
            }
        }
    );
}

$(function(){
    $("#spam_button").click(SPAM.spam);
});

ビュー

Django のビューは HTML 文章しか返せないということはなく、 XML でも画像でも好きなものを返してかまわない。 JSON を返すには HttpResponse(content, mimetype="text/javascript") のようにする。 content 引数に与える JSON を生成するには json モジュールの dumps 関数を使用すると便利(ただし Python 2.6 以降。それ以前では標準入りしていなかったので simplejsondjango.utils.simplejson を。 2.6 の json モジュールと同じもの)。 HttpResponse のドキュメントは http://djangoproject.jp/doc/ja/1.0/ref/request-response.html#httpresponse にある。

なお、この例では POST 以外の通信には問答無用で 404 Not Found 応答するようにしてある。フォーム処理関連のビューなのでこうしてみた。データを取り出すだけのビューならば GET などに応答するように作ってもよいかも。

import json
from django.http import HttpResponse, Http404
from spam.forms import SpamForm

def spam(request):
    if request.method == 'POST':
        form = SpamForm(request.POST)
        if form.is_valid():
            # 送られてきたデータは form.cleaned_data でアクセスできる
            # 何か処理して…
            # 返すデータを作成
            content = json.dumps({"result": "success"}) # 仮データ
            return  HttpResponse(content, mimetype="text/javascript")
    raise Http404