Table of Contents

หน้านี้เป็นส่วนหนึ่งของตัวอย่างการพัฒนาโปรแกรมด้วย Django: uquiz

หน้าที่เป็นตัวอย่างการใช้งานฟอร์มใน Django ผ่านทางระบบฟอร์ม อ่านข้อมูลเกี่ยวกับการจัดการฟอร์มเบื้องต้นได้จากคู่มือ Django และอ่านการใช้ระบบฟอร์มได้จากคู่มือเช่นเดียวกัน

สร้าง form และแสดง form

เพิ่ม class QuizInfoForm ลงใน quiz/views.py พร้อมด้วยวิวฟังก์ชัน new ที่แสดง form นี้

สังเกตว่า เราไม่ได้ให้ผู้ใช้ระบุ is_enabled ในฟอร์มนี้ เพราะเราจะให้สถานะเริ่มต้นของ quiz เป็นแบบยังไม่เปิดใช้งานจนกว่าผู้ใช้จะระบุต่อไป

--- a/quiz/views.py	Mon Sep 14 08:10:54 2009 +0700
+++ b/quiz/views.py	Mon Sep 14 08:16:55 2009 +0700
@@ -10,3 +10,12 @@
     quizes = Quiz.objects.filter(is_enabled=True).all()
     return render_to_response("quiz/list.html",
                               { 'quizes': quizes })
+
+class QuizInfoForm(forms.Form):
+    title = forms.CharField()
+    description = forms.CharField()
+
+def new(request):
+    form = QuizInfoForm()
+    return render_to_response("quiz/new.html",
+                              { 'form': form })

จากนั้นไปเพิ่ม template quiz/new.html

{% extends "base.html" %}
 
{% block content %}
<h2>Quiz creation</h2>
<p>
  {{ form.as_p }}
</p>
{% endblock %}

และสุดท้ายไปเพิ่ม url mapping ใน urls.py เราจะ map url new-quiz ให้กับวิวนี้

--- a/urls.py	Mon Sep 14 08:10:54 2009 +0700
+++ b/urls.py	Mon Sep 14 08:16:55 2009 +0700
@@ -8,6 +8,7 @@
 urlpatterns = patterns('',
     (r'^$', 'quiz.views.index'),
     (r'^list/$', 'quiz.views.list'),
+    (r'^new-quiz/$', 'quiz.views.new'),
     # Example:
     # (r'^uquiz/', include('uquiz.foo.urls')),

ทดลองใช้โดยเรียก http://localhost:8000/new-quiz/

เพิ่มลิงก์จากหน้าแรก

แก้ template quiz/index.html ให้แสดงลิงก์ไปยังหน้าสร้าง quiz

--- a/templates/quiz/index.html	Mon Sep 14 08:19:49 2009 +0700
+++ b/templates/quiz/index.html	Mon Sep 14 08:20:56 2009 +0700
@@ -7,7 +7,7 @@
 <p>
   What you can do here:
   <ul>
-    <li>Create quizes</li>
+    <li><a href="{% url quiz.views.new %}">Create quizes</a></li>
     <li><a href="{% url quiz.views.list %}">Play quizes</a></li>
   </ul>
 </p>

ประมวลผลฟอร์ม (รับค่า)

เราจะแก้ template โดยเพิ่ม tag ส่วนของ form และปุ่ม submit สังเกตว่าที่ action เราจะระบุไปที่วิวฟังก์ชันเดิม (โดยใช้ template tag url) แต่จะระบุวิธีการเรียกใช้ (method) เป็น post

--- a/templates/quiz/new.html	Mon Sep 14 08:34:11 2009 +0700
+++ b/templates/quiz/new.html	Mon Sep 14 08:38:57 2009 +0700
@@ -3,6 +3,9 @@
 {% block content %}
 <h2>Quiz creation</h2>
 <p>
-  {{ form.as_p }}
+  <form action="{% url quiz.views.new %}" method="post">
+    {{ form.as_p }}
+    <input type="submit" value="Create quiz"/>
+  </form>
 </p>
 {% endblock %}

จากนั้นเราจะแก้วิวฟังก์ชันให้รับและตรวจสอบฟอร์ม สังเกตว่าเราจะใช้วิวฟังก์ชันเดิม แต่เราจะเพิ่มการตรวจสอบ request.method ว่าเรียกเข้ามาแบบ post หรือไม่

--- a/quiz/views.py	Mon Sep 14 08:34:11 2009 +0700
+++ b/quiz/views.py	Mon Sep 14 08:38:57 2009 +0700
@@ -16,6 +16,13 @@
     description = forms.CharField()
 
 def new(request):
-    form = QuizInfoForm()
+    if request.method=="POST":
+        form = QuizInfoForm(request.POST)
+        if form.is_valid():
+            print "Title:", form.cleaned_data['title']
+            print "Description:", form.cleaned_data['description']
+            return
+    else:
+        form = QuizInfoForm()
     return render_to_response("quiz/new.html",
                               { 'form': form })

โปรแกรมด้านบนจะเรียก is_valid เพื่อตรวจสอบฟอร์ม ถ้าตรวจสอบไม่ผ่านจะส่งกลับไปแสดงผลพร้อมด้วย error message (ให้ทดลองดู)

แต่ถ้าฟอร์มถูกต้องโปรแกรมจะพิมพ์ค่าออกมาที่ console ส่วนในเว็บจะมี error จาก django ขึ้น ว่า The view quiz.views.new didn't return an HttpResponse object.

ถ้าเราไปดูที่ console (ใน terminal เราเรียก runserver) เราจะพบข้อความประมาณด้านล่างนี้:

Title: test quiz
Description: this is a test
[13/Sep/2009 20:42:08] "POST /new-quiz/ HTTP/1.1" 500 49981

ประมวลผลฟอร์ม (สร้าง quiz แล้ว redirect)

เราจะเพิ่มโปรแกรมส่วนประมวลผลฟอร์มเมื่อฟอร์มผ่านการตรวจสอบ เราจะสร้าง quiz ขึ้นมาแล้วใส่ค่าที่ได้จากฟอร์มลงไป ในที่นื้เราจะกำหนดค่า is_enabled ให้เป็น True ไปก่อน เพื่อที่เราจะได้เข้าไปตรวจสอบความถูกต้องของการเพิ่มข้อมูลได้จากหน้ารายการ quiz

เมื่อเราสร้าง quiz เสร็จแล้ว เราก็จะ redirect ผู้ใช้กลับไปหน้าแรก โดยการคืนวัตถุของคลาส HttpResponseRedirect กลับไป

--- a/quiz/views.py	Mon Sep 14 08:45:28 2009 +0700
+++ b/quiz/views.py	Mon Sep 14 08:46:42 2009 +0700
@@ -1,4 +1,5 @@
 from django.shortcuts import render_to_response
+from django.http import HttpResponseRedirect
 from django import forms
 
 from models import Quiz
@@ -19,9 +20,12 @@
     if request.method=="POST":
         form = QuizInfoForm(request.POST)
         if form.is_valid():
-            print "Title:", form.cleaned_data['title']
-            print "Description:", form.cleaned_data['description']
-            return
+            quiz = Quiz()
+            quiz.title = form.cleaned_data['title']
+            quiz.description = form.cleaned_data['description']
+            quiz.is_enabled = True
+            quiz.save()
+            return HttpResponseRedirect('/')
     else:
         form = QuizInfoForm()
     return render_to_response("quiz/new.html",

การใช้ reverse แทนการระบุ url โดยตรง

เช่นเดียวกับใน template เราไม่ต้องการระบุ url ลงไปตรง ๆ ในโปรแกรม ดังนั้นจากโปรแกรมข้างต้นที่ระบุ / เมื่อสร้าง HttpResponseRedirect เราจะหา url ผ่านทางฟังก์ชัน reverse ที่อยู่ในโมดูล django.core.urlresolvers (อย่าลืม import)

--- a/quiz/views.py	Mon Sep 14 08:49:41 2009 +0700
+++ b/quiz/views.py	Mon Sep 14 08:54:47 2009 +0700
@@ -1,5 +1,6 @@
 from django.shortcuts import render_to_response
 from django.http import HttpResponseRedirect
+from django.core.urlresolvers import reverse
 from django import forms
 
 from models import Quiz
@@ -25,7 +26,7 @@
             quiz.description = form.cleaned_data['description']
             quiz.is_enabled = True
             quiz.save()
-            return HttpResponseRedirect('/')
+            return HttpResponseRedirect(reverse('quiz.views.index'))
     else:
         form = QuizInfoForm()
     return render_to_response("quiz/new.html",

ต่อจากนี้

เราวางแผนไว้ว่าเมื่อสร้าง quiz เสร็จ เราจะพาผู้ใช้ไปหน้าสำหรับใส่คำถามและจัดการ quiz ดังนั้นแทนที่เราจะ redirect กลับไปที่หน้าแรก เราควรจะ redirect ไปหน้าจัดการ quiz ซึ่งจะมี url เฉพาะสำหรับผู้สร้าง quiz เท่านั้น เราจะเขียนในส่วนนี้ในโอกาสต่อไป (โปรดติดตาม)