มือใหม่ Django part 3: Admin page
มือใหม่และผมได้เรียนรู้ร่วมกันแล้วว่า Django จะให้เรานิยามสิ่งที่ต้องการก่อน จากนั้นจึงค่อยสร้างและใช้งานในภายหลัง เราได้รู้จัก view และ model กันไปแล้ว หนนี้มาดูอีกว่า Django มีเครื่องมืออะไรเตรียมไว้ให้พวกเราได้ว้าวกันอีกไหม
ความเดิมจาก part ก่อนหน้า
เข้าประเด็นเลย งานปกติที่เรามักทำกันบ่อยครั้งกับข้อมูลในตารางของฐานข้อมูลคือ
- เพิ่ม (create)
- ดู (read)
- ปรับปรุง (update)
- ลบ (delete)
รวมแล้วเรียกว่า CRUD
ข้อสงสัยปนความเกียจคร้านมีอยู่ว่า ถ้าจะเขียนเว็บสักหลายหน้าเพื่อทำเรื่องเหล่านี้มันคงเสียเวลาน่าดู เนื่องจากข้อมูล (ขอเรียกว่า content หรือ data) ก็มีเยอะแยะไปหมด มือใหม่อาจบอกว่าไม่เห็นยากก็ไปใช้โปรแกรมจัดการฐานข้อมูลเลยสิ เขียน SQL เอาครับ แต่เปล่าเลย…ถ้าเราจะสร้างเว็บในการจัดการ content อย่าง CMS (ย่อมาจาก Content Management System) หรือเพื่ออำนวยความสะดวกแก่ผู้ใช้งานแบบจริงจัง พวกเขาไม่ต้องการเครื่องมือหลายตัวเพื่อทำงานชิ้นเดียวให้สำเร็จ ตรงกันข้ามพวกเขาจะถามหาสิทธิ์ในการเข้าไปแก้ไข content ที่ต้องการอย่างมีระบบ ง่ายดายและรู้สึกปลอดภัยมากกว่า ดังนั้นโยนโปรแกรมพวก command-line client หรือโปรแกรมอย่าง DB Browser for SQLite ออกจากหัวไปก่อน
กลับมาที่ข้อสงสัยปนความเกียจคร้าน Django จึงเสนอหนทางดูแลส่วนนี้โดยมันจะสร้างหน้าเว็บฝั่งผู้ดูแลระบบที่เรียกว่า content publishers ให้ เมื่อผู้ใช้งานที่เรียกว่า admin หรือ manager เข้าสู่ระบบแล้วก็จะสามารถ CRUD กับ content ที่ต้องการนั้นได้ทันที — จบปิ้ง
มาถึงตรงนี้ผมขอสรุปให้เห็นภาพง่ายๆดังนี้
- Django จะแยกผู้ใช้งานออกเป็น 2 กลุ่ม คือ visitors กับ managers
- visitors คือกลุ่มลูกค้าที่จะเห็น public site
- managers คือกลุ่มผู้ดูแลที่จะเห็น content publishers
- content ที่ปรากฏ ณ public site จะถูกเพิ่ม แก้ไขและลบโดยกลุ่ม managers
จาก part ที่ผ่านมาลองกลับไปรัน python3 manage.py runserver
สืบเนื่องจากเราได้ migrate apps เป็นที่เรียบร้อย ผลคือ http://localhost:8000/polls/
ยังใช้ได้ปกติ
Python shell
เป็น command-line interface ที่ใช้ interactive กับ Django APIs มาลองกันครับ
python3 manage.py shell
ผลลัพธ์
ลอง import คลาส Question และ Choice มาใช้งาน
from polls.models import Question, Choice
จากนั้นขอดู Question ทั้งหมด
Question.objects.all()
หรือขอดู Choice ทั้งหมด
Choice.objects.all()
ผลคือ <QuerySet []> แปลว่าว่างเปล่า ไม่มีของ
สร้าง Question
Question มี date time ฉะนั้นเพิ่ม import timezone ด้วย
from django.utils import timezone
แล้วพิมพ์คำถามเหมือนใน Python คือประกาศตัวแปรแล้วให้ค่า
q = Question(question_text="President of Thailand?", pub_date=timezone.now())
จากนั้นบันทึกลงฐานข้อมูล
q.save()
อยากเห็น id ที่ฐานข้อมูลสร้างให้ หรืออยากเห็น question_text หรืออยากเห็น pub_date ใช้เครื่องหมาย . ต่อท้ายตัวแปรที่สร้างได้เลย เช่น q.id
, q.question_text
, q.pub_date
ขอแก้ไข question_text หน่อย
q.question_text="เลือกใครเป็นนายก?"
บันทึก
q.save()
จากนั้นขอดู Question ทั้งหมดอีกครา Question.objects.all()
ผลคือ
<QuerySet [<Question: Question object (1)>]>
อ่านไม่ออก 555+ เพื่อแก้ไขเรื่องนี้จะต้องทำ to string ให้กับคลาส Question
To String
ทำก็ต่อเมื่อต้องการอ่านผลลัพธ์จากออบเจกต์ของคลาสใน command-line
เปิดไฟล์ polls/models.py
เพิ่มฟังก์ชัน __str__ แล้วโยนตัวมันเองเป็น argument แรก
from django.db import modelsclass Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
def __str__(self):
return self.question_text
ขอทำ Choice ด้วยเลย
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
def __str__(self):
return self.choice_text
ทดสอบด้วยการออกจาก shell แล้วกลับเข้าไปใหม่
import Question แล้วเรียก Question.objects.all()
ผลลัพธ์
สร้าง Choice
เราสามารถสร้าง Choice ที่มีความสัมพันธ์หนึ่งต่อหลายกับ Question ได้ด้วยคำสั่ง _set
ตัวอย่างต่อไปนี้ หนึ่ง Question มีสาม Choices
from polls.models import Choice, Questionq = Question.objects.get(id=1)q.choice_set.create(choice_text="ลุงตู่", votes=0)q.choice_set.create(choice_text="พี่ธร", votes=0)q.choice_set.create(choice_text="พี่เต้", votes=0)
หากว่าต้องการดู Choices ทั้งหมดซึ่งได้ผลลัพธ์ไม่ต่างจาก Choice.objects.all()
ก็ว่า
q.choice_set.all()
หรือนับจำนวนก็ว่า
q.choice_set.count()
ยังมีอีกหลายคำสั่งที่เกี่ยวข้องกับความสัมพันธ์ของ model หรือตารางในฐานข้อมูล สามารถอ่านเพิ่มเติม ที่นี่
Admin Page
เพื่อจะได้ชมว่า Django ได้สร้างหน้าเว็บฝั่งผู้ดูแลระบบที่เรียกว่า content publishers ให้อย่างไร สิ่งแรกที่เราต้องมีคือ admin user สร้างโดยคำสั่งนี้ครับ
python3 manage.py createsuperuser
Django จะให้กรอก username, email และ password
ผมได้เพิ่ม
- username: admin
- email: admin@mail.com
- password: 1234
password ที่เดาได้ง่ายนั้นไม่ปลอดภัย Django จึงเตือนในเรื่องนี้ ทว่าสุดท้ายก็แล้วแต่ความต้องการของเรา
เรียกไปที่ http://localhost:8000/admin/
ผลลัพธ์
กรอก username และ password ตามระเบียบจ้า
ว้าว! ผมจำได้ว่าเพื่อนผมร้องว้าวออกมาเมื่อเห็นหน้านี้ครั้งแรก ราวกับว่าเขาอยู่ในอาณาจักรของ backend มาชั่วชีวิตเพิ่งได้เห็นว่าภาษา Python สามารถสร้าง frontend ได้ด้วย แลมันงดงามเหลือเหลือคณานับ ตาสว่าง!
แต่สามวินาทีหลังจากนั้นความฝันพลันมลายด้วยความสงสัยพร้อมกับคำถามที่ฟังแล้วขบขัน “ไหนล่ะพี่ธร?”
อันที่จริงมันต้องถามว่า Question และ Choice อยู่ที่ไหน?
Make the Polls app modifiable in the admin
เราจำต้องลงทะเบียนให้ admin page ทราบก่อนว่าจะเอา models ใดมาโชว์บ้าง
เปิดไฟล์ polls/admin.py แล้วเพิ่ม Question กับ Choice
from django.contrib import admin
from .models import Question, Choiceadmin.site.register(Question)
admin.site.register(Choice)
ไม่จำเป็นต้อง restart server ใหม่ แค่ reload page เท่านั้น
ผลลัพธ์
กดเข้าไปชม Question
เลือกคำถามแรก กดเข้าไปเพื่อแก้ไขและบันทึกได้
หรือกดเข้าไปชม Choice จะเพิ่ม แก้ไข ลบ ตามใจปรารถนา
ทบทวน สิ่งนี้จึงเรียกว่า CRUD อันหมายถึง create, read, update และ delete ซึ่งมักทำบ่อยๆกับข้อมูลในตารางฐานข้อมูลอยู่แล้ว แน่นอนว่า Django รู้จึงจัดการให้เสร็จสรรพ
โอกาสถัดไปเราจะมาต่อกันที่ view ของ Polls app เพื่อเอาโหวตมาแสดงผล สวัสดีจ้า