มือใหม่ Django part 2: Polls app

Phai Panda
5 min readFeb 11, 2021

--

ตอนที่แล้วเรา 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 ก่อนหน้านี้ทำให้ได้โครงสร้างดังรูป

mysite project structure

และหากเปิดด้วย MS VS Code

mysite in MS VS Code

สร้าง Polls app

จาก directory ดังรูปข้างต้นเราจะสร้าง app ชื่อ polls พิมพ์

python3 manage.py startapp polls

ผลลัพธ์

create a polls app

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.")
นิยาม index.html

การนิยามที่เพิ่งเขียนไปนี้บอกให้ 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 views
urlpatterns = [
path('', views.index, name='index'),
]
นิยาม URLconf ของ Polls app

เมื่อมี URLconf ของ Polls app แล้ว (จะเรียกว่า Python module ก็ได้) ต่อไปก็เป็นทีของโปรเจกต์ mysite

เปิดไฟล์ mysite/urls.py มองไปด้านล่าง พิมพ์เพิ่ม

from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('polls/', include('polls.urls')),
]
นิยาม URLconf ของโปรเจกต์ mysite

รัน

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 ให้กับพวกเราพร้อมกับพูดว่า “จงรับไปเถิดเหล่าสาวกเอ๋ย~” ตั้งแต่ครั้งแรกที่รันแล้ว

SQLite by default

ตัวแปรที่จำเป็นต่อการสร้าง 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
migrate some apps for create table

ผลลัพธ์เราจะได้ตารางในฐานข้อมูล กรณีของเราก็คือ SQLite

เพื่อจะเข้าชมตารางและข้อมูลในฐานข้อมูลเชื่อว่าหลายคนชอบใช้ command-line client แต่ผมนึกอยากเห็นเป็น interface ง่ายๆ ผมจึงไปโหลดโปรแกรม DB Browser for SQLite มาใช้ ที่นี่

DB Browser for SQLite

use DB Browser for SQLite open db.sqlite3 database file
เห็นตารางพวกนั้นไหม นั่นแหละ apps ในตัวแปร INSTALLED_APPS

ถึงเวลาเรานิยาม 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)
create Question & Choice models

Activating models

เมื่อได้นิยามแล้วก็ต้องทำให้พวกมันมีชีวิตขึ้นมา คือกลายเป็นตารางจริงๆในฐานข้อมูล

เปิดไฟล์ polls/apps.py เห็นคลาส PollsConfig นั่นไหม เราต้องทำให้โปรเจกต์ mysite รู้จักมันให้ได้

Polls app apps.py pluggable

กลับมาที่โปรเจกต์ 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

ผลลัพธ์

แสดงเป็น SQL ให้ดูเลยว่าเดี๋ยวจะสร้างให้ตามนี้

มาถึงตรงนี้มือใหม่อาจอยากถามว่า Django รู้ได้อย่างไรว่าควรสร้าง SQL หน้าตาแบบไหนออกมา ในเมื่อฐานข้อมูลต่างยี่ห้อก็มักจะมีรูปแบบที่ผิดแปลกแตกต่างกันไม่มากก็น้อย คำตอบคือ ค่าของตัวแปร ENGINE ที่กำหนดไว้ใน mysite/settings.py

ถามว่าตอนนี้ตาราง Question และ Choice เกิดขึ้นหรือยัง ตอบว่ายังครับ

งั้นทำให้มันเกิดขึ้น พิมพ์

python3 manage.py migrate

ผลลัพธ์

หากใช้ DB Browser for SQLite ให้เลือกแท็บ Browse Data กดเครื่องหมาย refresh

เป็นอันว่าเราสามารถสร้างตารางจาก models เป็นผลสำเร็จ!

แต่ก่อนจะจากกันไป แบบสอนได้แนะนำขั้นตอนในการ migration ว่าประกอบด้วย 3 ขั้นตอนคือ

  1. นิยามหรือเปลี่ยนแปลง model ก่อน
  2. ทำคำสั่ง python3 manage.py makemigrations เพื่อบอก Django ให้ทราบการเปลี่ยนแปลง
  3. ทำคำสั่ง python3 manage.py migrate

--

--

No responses yet