มือใหม่ Django part 2: Polls app
ตอนที่แล้วเรา boot เว็บที่สร้างจาก Django framework จากศูนย์ ใช้การตั้งค่าโดย default ทั้งหมด บทความนี้เราจะลุยกันต่อกับ app ที่ชื่อ Polls ครับ
สำหรับเพื่อนมือใหม่ที่ต้องการความมันส์แรกเริ่ม
อย่างที่ผมมักจะทำบ่อยๆ ผมชอบที่จะศึกษาผ่านเว็บทางการของมัน เมื่อก่อน document อ่านยาก มาแบบภาษาไลบรารีที่บรรยายการทำงานของคลาสและฟังก์ชัน ก็ไม่เห็นภาพรวมว่ามันทำงานร่วมกันเป็นเรื่องราวได้อย่างไรนอกเสียจากว่าจะจับไทป์ให้มันตรงกัน สรุปคือจิ้นไม่ออกเลยทีเดียว
Google ไปว่า django polls app
ผลได้หน้านี้มา เลื่อนลงไปด้านล่างจ้า
Creating the Polls app
หัวข้อ creating the Polls app มันเป็นอย่างไรน้า เขาจะสอนความคิดอะไรเรา?
- แบบสอนกล่าวว่า Django จะสร้าง structure ของโปรเจกต์ให้ งานของเราคือเอาหัวไปเขียน Python อย่างเดียวพอ จริงสิ?
- คำว่าโปรเจกต์ (project) ต่างจากคำว่า app เนื่องจากหนึ่งโปรเจกต์ของ Django สามารถประกอบไปด้วยหลาย app
- ยิ่งไปกว่านั้นหนึ่ง app ใดๆสามารถอยู่ได้ในหลายโปรเจกต์
creating the Polls app จะสอนการสร้าง app ที่อยู่ใน directory เดียวกับไฟล์ manage.py และไฟล์นี้อยู่ภายนอก mysite folder
ทบทวน
คำสั่ง django-admin startproject mysite
จาก part ก่อนหน้านี้ทำให้ได้โครงสร้างดังรูป
และหากเปิดด้วย MS VS Code
สร้าง Polls app
จาก directory ดังรูปข้างต้นเราจะสร้าง app ชื่อ polls พิมพ์
python3 manage.py startapp polls
ผลลัพธ์
Django จะสร้าง polls folder ขึ้นมาเสมอตำแหน่งไฟล์ manage.py
Views and Models
เบื้องต้นนี้พวกเราควรทราบว่า app ที่ถูกสร้างจะประกอบด้วย view และ model
- view ก็คือ HTML
- model ก็คือตารางของฐานข้อมูล
สร้าง view ให้กับ Polls app
Django ให้นิยาม view ไว้ในไฟล์ชื่อ views.py อย่าได้รอช้าเข้าไปเขียน Hello World กันเถอะ
เปิดไฟล์ polls/views.py แล้วพิมพ์
from django.http import HttpResponsedef index(req):
return HttpResponse("Hello World!, you are at the polls index.")
การนิยามที่เพิ่งเขียนไปนี้บอกให้ Django ทราบว่าเราต้องการหน้า index.html ในหน้านี้บรรจุข้อความ Hello World!, you are at the polls index.
ถัดจากนั้นเราต้องเชื่อมโยงมันเข้ากับโปรเจกต์ mysite และ Django เรียกการกระทำนี้ว่า URLconf
เราจะเพิ่ม URLconf ใหักับ Polls app โดยสร้างไฟล์ชื่อ urls.py ไว้เสมอตำแหน่ง views.py
เปิดไฟล์ polls/urls.py แล้วพิมพ์
from django.urls import path
from . import viewsurlpatterns = [
path('', views.index, name='index'),
]
เมื่อมี URLconf ของ Polls app แล้ว (จะเรียกว่า Python module ก็ได้) ต่อไปก็เป็นทีของโปรเจกต์ mysite
เปิดไฟล์ mysite/urls.py มองไปด้านล่าง พิมพ์เพิ่ม
from django.contrib import admin
from django.urls import path, includeurlpatterns = [
path('admin/', admin.site.urls),
path('polls/', include('polls.urls')),
]
รัน
python3 manage.py runserver
เปิด browser http://localhost:8000/polls/
ผลลัพธ์
สิ่งที่เราสังเกตเห็นจากสิ่งที่เพิ่งเกิดขึ้นคือ URLconf สร้างการเชื่อมโยงระหว่าง app กับโปรเจกต์ ในที่นี้มันได้ผูก polls app เข้ากับ mysite
มือใหม่ควรทราบว่าฟังก์ชัน path ในโค้ดข้างต้นต้องการ arguments (ค่าที่ต้องส่งให้มัน) เท่าที่จำเป็น 2 ค่าตามลำดับได้แก่
- route ค่าของสตริง URL ที่ต้องการให้เรียกซึ่งสามารถตั้งได้ตามใจชอบ เช่น
admin/
myapp/1234/
polls/
about-me/
- view ค่าที่ได้จากการทำงานของฟังก์ชัน include ซึ่งจะได้รับออบเจกต์ HttpRequest เป็น argument แรกโดยอัตโนมัติ จากตัวอย่าง
include('polls.urls')
จะมองไปยัง polls app แล้วเรียกหาไฟล์ urls.py
สร้าง Model ให้กับ Polls app
เนื่องจากผมเรียนรู้จากแบบสอน (tutorial) ถัดจากหัวข้อสร้าง view เขาก็นำเราสู่การสร้าง model โดยจะสร้างออกมา 2 models ได้แก่
- Question คือคำถาม
- Choice คือทางเลือก
หนึ่งคำถามใดๆสามารถมีได้หลายทางเลือก แต่ละทางเลือกอาจเป็นคำตอบที่ถูกหรือถูกต้องที่สุดซึ่งจะมีคะแนนการโหวตให้ด้วย
ตัวอย่าง
คำถาม: เลือกใครเป็นนายก?
ทางเลือกแรก: ลุงตู่ จำนวนโหวต 3
ทางเลือกสอง: พี่ธร จำนวนโหวต 2
ทางเลือกสาม: พี่เต้ จำนวนโหวต 1
ทางเลือกสี่: ไม่ออกเสียง จำนวนโหวต 4
model ก็คือตารางในฐานข้อมูลที่เราเลือกและโดย default แล้วเมื่อผมไม่ได้กำหนดฐานข้อมูลใดๆ มือใหม่ที่ช่างสังเกตจะพบว่า Django ยิ้มและมอบ SQLite ให้กับพวกเราพร้อมกับพูดว่า “จงรับไปเถิดเหล่าสาวกเอ๋ย~” ตั้งแต่ครั้งแรกที่รันแล้ว
ตัวแปรที่จำเป็นต่อการสร้าง Models
เปิดไฟล์ mysite/settings.py เบื้องต้นนี้มี 3 ตัวแปรที่เราต้องให้ความสนใจ
- DATABASES
- TIME_ZONE
- INSTALLED_APPS
DATABASES
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
ส่วนนี้ประกอบด้วย
- ENGINE คือ engine ที่ทำให้ Django เข้าใจและทำงานกับฐานข้อมูลที่เลือกได้ มีอยู่หลายตัว ได้แก่
django.db.backends.sqlite3
,django.db.backends.postgresql
,django.db.backends.mysql
,django.db.backends.oracle
และอื่นๆ ที่นี่ - NAME คือที่อยู่และชื่อของฐานข้อมูลที่อ้างอิง
หากเราใช้ฐานข้อมูลอื่นที่ไม่ใช่ SQLite จะต้องกำหนดค่าของ USER, PASSWORD และ HOST ลงไปด้วย ตัวอย่าง ที่นี่ และให้แน่ใจว่าได้สร้างฐานข้อมูลไว้แล้ว
CREATE DATABASE database_name;
TIME_ZONE
มีฟิลด์ที่เกี่ยวข้องกับเวลาที่มือใหม่น่าจะเคยเห็นหรือผ่านหูมาบ้าง เช่น DateTime จำต้องระบุ time zone เพื่อให้ server ทราบว่าจะต้องให้ค่าเวลาของโซนบวกหรือลบเท่าไร หากไม่มีการระบุตัวแปร TIME_ZONE เจ้า Django จะใช้ค่า default คือ America/Chicago ทว่า Django ก็ได้เขียนค่านี้ให้เราแล้ว มันกำหนดไว้เป็น UTC
time zone อื่นๆดูได้ ที่นี่
INSTALLED_APPS
ตัวแปรนี้จัดว่าเป็นหัวใจของการประกอบประดา app อื่นทั้งหลายเข้าโปรเจกต์
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
ไม่ชอบไม่ใช้ app ไหนก็เอาออกได้ตามใจ
เบื้องต้นนี้เราจะใช้งานมันทั้งหมดตามค่า default ที่ให้มา
เพื่อจะสร้างตารางในฐานข้อมูล เราต้องใช้คำสั่ง migrate
จงพิมพ์ไปว่า
python3 manage.py migrate
ผลลัพธ์เราจะได้ตารางในฐานข้อมูล กรณีของเราก็คือ SQLite
เพื่อจะเข้าชมตารางและข้อมูลในฐานข้อมูลเชื่อว่าหลายคนชอบใช้ command-line client แต่ผมนึกอยากเห็นเป็น interface ง่ายๆ ผมจึงไปโหลดโปรแกรม DB Browser for SQLite มาใช้ ที่นี่
DB Browser for SQLite
ถึงเวลาเรานิยาม models และสร้างตารางเองบ้างแล้วครับ
Question Model
- ให้ชื่อว่า Question
- ประกอบด้วย 2 attributes คือ question_text และ pub_date
- question_text คือคำถาม มีชนิดเป็น Char ความยาวไม่เกิน 200 อักษร
- pub_date ย่อมาจาก publication date คือเวลาที่สร้างคำถาม มีชนิดเป็น DateTime
Choice Model
- ให้ชื่อว่า Choice
- ประกอบด้วย 3 attributes คือ question, choice_text และ votes
- question จะให้เป็น ForeignKey ชี้ไปยัง Question และจะกำหนดให้ถูกลบไปพร้อมกับ Question ที่สัมพันธ์กันนั้นด้วย
- choice_text คือทางเลือกของคำถามใดๆ มีชนิดเป็น Char ความยาวไม่เกิน 200 อักษร
- votes คือโหวตหรือการออกเสียง ให้มีชนิดเป็น Integer และจะให้ค่าเป็น 0 ไว้ก่อน
กลับมาที่ Polls app เปิดไฟล์ polls/models.py แล้วจงนิยาม models ที่เกริ่นไว้
from django.db import modelsclass Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
Activating models
เมื่อได้นิยามแล้วก็ต้องทำให้พวกมันมีชีวิตขึ้นมา คือกลายเป็นตารางจริงๆในฐานข้อมูล
เปิดไฟล์ polls/apps.py เห็นคลาส PollsConfig นั่นไหม เราต้องทำให้โปรเจกต์ mysite รู้จักมันให้ได้
กลับมาที่โปรเจกต์ mysite เปิดไฟล์ mysite/settings.py แล้วเพิ่มคลาส PollsConfig ไว้กับพวกที่เหลือในตัวแปร INSTALLED_APPS แบบนี้ครับ
INSTALLED_APPS = [
'polls.apps.PollsConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
Django เรียก polls.apps.PollsConfig ว่า dotted path เพื่อนๆลองไล่ดูสิครับ มันคือชื่อ folder ตามด้วยชื่อไฟล์และก็ชื่อคลาส
makemigrations
คำสั่งนี้บอกให้ Django ทราบว่าเกิดการเปลี่ยนแปลง (change) กับ model ใดและต้องการนำผลของการเปลี่ยนแปลงนี้ทำ migration ต่อไป
python3 manage.py makemigrations polls
ผลลัพธ์
เกิดการสร้างไฟล์ชื่อ 0001_initial.py อยู่ใน polls/migrations ตามไปดูสิ
ไฟล์ 0001_initial.py นี้คือตรงกลางระหว่างสิ่งที่เรานิยามกับตารางในฐานข้อมูล ประโยชน์คือเราสามารถปรับแต่งได้อีกก่อนจะสั่งสร้างตารางจริงๆ (คำสั่ง migrate)
ก่อนจะสั่ง migrate มีอีกคำสั่งที่อยากให้รู้จักนั่นคือ sqlmigrate
ลองพิมพ์
python3 manage.py sqlmigrate polls 0001
เมื่อ 0001 คือไฟล์ 0001_initial.py ใน Polls app
ผลลัพธ์
มาถึงตรงนี้มือใหม่อาจอยากถามว่า Django รู้ได้อย่างไรว่าควรสร้าง SQL หน้าตาแบบไหนออกมา ในเมื่อฐานข้อมูลต่างยี่ห้อก็มักจะมีรูปแบบที่ผิดแปลกแตกต่างกันไม่มากก็น้อย คำตอบคือ ค่าของตัวแปร ENGINE ที่กำหนดไว้ใน mysite/settings.py
ถามว่าตอนนี้ตาราง Question และ Choice เกิดขึ้นหรือยัง ตอบว่ายังครับ
งั้นทำให้มันเกิดขึ้น พิมพ์
python3 manage.py migrate
ผลลัพธ์
หากใช้ DB Browser for SQLite ให้เลือกแท็บ Browse Data กดเครื่องหมาย refresh
เป็นอันว่าเราสามารถสร้างตารางจาก models เป็นผลสำเร็จ!
แต่ก่อนจะจากกันไป แบบสอนได้แนะนำขั้นตอนในการ migration ว่าประกอบด้วย 3 ขั้นตอนคือ
- นิยามหรือเปลี่ยนแปลง model ก่อน
- ทำคำสั่ง
python3 manage.py makemigrations
เพื่อบอก Django ให้ทราบการเปลี่ยนแปลง - ทำคำสั่ง
python3 manage.py migrate
อ่านต่อ
อ้างอิง
https://docs.djangoproject.com/en/3.1/intro/tutorial02/