1.รูปแบบของ Database ที่เลือกใช้นั้นจะเป็นของ sqlite3 ซึ่งมีอยู่แล้วใน Django จึงไม่ต้องทำการแก้ไขหรือตั้งค่าอะไรเพิ่มเติม แต่หากอยากใช้ Database ตัวอื่นศึกษาเพิ่มเติมได้ที่นี่ คลิก
2.เริ่มสร้าง Model โดยการพิม python manage.py startapp ชื่อแอพ ใน Terminal ในตัวอย่างจะใช้ books
python manage.py startapp booksซึ่งจะได้โฟลเดอร์ใหม่ขึ้นมาชื่อ books และมีโครงสร้างภายในดังนี้
books/
admin.py3.เปิดไฟล์ models.py แล้วแก้ไขไฟล์ดังนี้
__init__.py
models.py
tests.py
views.py
from django.db import models
class Publisher(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=50)
city = models.CharField(max_length=60)
state_province = models.CharField(max_length=30)
country = models.CharField(max_length=50)
website = models.URLField()
class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField()
class Book(models.Model):จากโค้ดที่แก้ไขนั้นได้ import models จาก django.db มาซึ่งเป็น API พื้นฐานที่มากับ Django เป็นโครงร่างของ Class Models ที่ให้เรานำมาใช้งานได้ซึ่งในตัวอย่างนี้แบ่งออกเป็นหลักๆ 3 Class ใหญ่คือ Publisher, Author, Book
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
publication_date = models.DateField()
ซึ่งใน Publisher จะเป็น Class ที่เก็บ name, address, city, state_province, country ซึ่งเก็บข้อมูลในรูปแบบของ CharField ซึ่งสามารถเก็บได้สูงสุด 30, 50, 60, 30, 50 ตัวอักษรตามลำดับและ website ซึ่งเป็นรูปแบบ URLField เอาไว้เก็บ URL โดยเฉพาะซึ่งคุณสมบัติก็คล้ายๆกับ CharField แต่หากเราไม่กำหนด max_length เองตัว URLField จะกำหนดให้เองไว้ที่ 200 ตัวอักษรทำให้ถูกลิมิตจำนวนตัวอักษรไว้ที่ 200 ตัวโดยอัตโนมัติ ซึ่งจะแตกต่างจาก CharField หาก CharField ไม่กำหนดค่า max_length นั้นก็จะใส่ตัวอักษรได้ไม่จำกัดนั่นเอง และนอกจากนี้ URLField ยังสามารถตรวจสอบได้ว่าค่าที่ใส่มาในช่องนั้นเป็น URL หรือไม่โดยหากไม่มี http:// นำหน้าชื่อเว็บแล้วก็จะถือว่าค่าที่กรอกนั้นผิดและต้องกรอกให้ถูกจึงจะบันทึกค่าลงใน Database ได้
ในส่วนของ Author เป็น Class ที่เก็บ first_name, last_name ซึ่งจะเก็บข้อมูลในรูปแบบ CharField ที่มีความยาว 30, 40 ตามลำดับ และมี email ซึ่งเก็บข้อมูลแบบ EmailField ซึ่งคล้ายๆกับ CharField แต่จะถูกลิมิตจำนวนตัวอักษรไว้ที่ 75 ตัวอักษรหากเราไม่กำหนด max_length เองและยังสามารถตรวจสอบได้ว่าค่าที่เรากรอกนั้นเป็น e-mail หรือไม่หากไม่ใช่ก็ต้องกรอกใหม่อีกเช่นกัน
สุดท้าย Book เป็น Class ที่เก็บข้อมูล title ซึ่งเป็น CharField ที่กำหนดความยาวไว้ที่ 100 ตัวอักษร authors เก็บข้อมูลแบบ ManyToManyField ซึ่งเป็น Object ซึ่งเก็บข้อมูลของ Object จาก Author ได้หลายๆ Object เหตุผลเพราะหนังสือเล่นนึงสามารถมีผู้แต่งได้หลายคนดังนั้นจึงต้องมีการเก็บข้อมูลที่สามารถอ้างอิงถึง Author ได้หลายๆคน publisher เก็บข้อมูลแบบ ForeignKey ซึ่งจะเป็นการกำหนด Object ที่อ้างอิงถึงจาก Class Publisher โดยมีได้เพียงแค่ 1 ตัวเท่านั้น publication_date เก็บข้อมูลแบบ DateField ซึ่งเป็น Field ที่เก็บข้อมูลของวันที่เท่านั้นซึ่งเก็บในรูปแบบของ ปี-เดือน-วันที่ โดยปีที่ใช้เป็นแบบ ค.ศ. นั่นเอง
4.จากนั้นกลับไปแก้ไขไฟล์ settings.py ที่อยู่ในโฟลเดอร์ mysite โดยเข้าไปเพิ่ม 'books', ในส่วนของ INSTALLED_APPS จะได้รูปแบบดังนี้
INSTALLED_APPS = (5.จากนั้นลองพิม python manage.py validate ใน Terminal หากเราทำทุกอย่างถูกต้องได้ Output กลับมาเป็น 0 errors found แต่หากมี error ให้ลองเช็คใน models.py ว่ามีส่วนไหนที่ผิดหรือไม่จากนั้นแก้ไขจนเสร็จแล้วลองพิมคำสั่งอีกครั้งหากยังมี error ก็ให้แก้ไปเรื่อยๆจนกว่าจะได้เป็น 0 errors found
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'books',
)
ซึ่ง validate เป็นการเช็คว่า models ที่เราเขียนขึ้นมานั้นมีส่วนไหนที่ syntax และ logic ผิดหรือไม่หากไม่ผิดก็จะได้ 0 errors found แต่หากมีที่ผิดก็จะฟ้อง error ขึ้นมาซึ่งเป็นตัวช่วยในการตรวจสอบว่า models ที่เราเขียนนั้นมีความถูกต้องมากน้อยเพียงใดนั่นเอง
6.จากนั้นพิม python manage.py sqlall books เพื่อให้ Django สร้างแบบฟอร์มของ Table สำหรับการใช้ในการสร้าง Database ขึ้นมาซึ่งจะได้หน้าตาประมาณนี้
BEGIN;ซึ่งการใช้ sqlall books ยังไม่ใช่การสร้าง Database แต่เป็นเพียงการสร้างฟอร์มซึ่งเราสามารถนำโค้ดข้างบนไปใส่ใน Database เองก็ได้หรือจะทำตามข้อต่อไปนี้
CREATE TABLE "books_publisher" (
"id" integer NOT NULL PRIMARY KEY,
"name" varchar(30) NOT NULL,
"address" varchar(50) NOT NULL,
"city" varchar(60) NOT NULL,
"state_province" varchar(30) NOT NULL,
"country" varchar(50) NOT NULL,
"website" varchar(200) NOT NULL
)
;
CREATE TABLE "books_author" (
"id" integer NOT NULL PRIMARY KEY,
"first_name" varchar(30) NOT NULL,
"last_name" varchar(40) NOT NULL,
"email" varchar(75) NOT NULL
)
;
CREATE TABLE "books_book_authors" (
"id" integer NOT NULL PRIMARY KEY,
"book_id" integer NOT NULL,
"author_id" integer NOT NULL REFERENCES "books_author" ("id"),
UNIQUE ("book_id", "author_id")
)
;
CREATE TABLE "books_book" (
"id" integer NOT NULL PRIMARY KEY,
"title" varchar(100) NOT NULL,
"publisher_id" integer NOT NULL REFERENCES "books_publisher" ("id"),
"publication_date" date NOT NULL
)
;
CREATE INDEX "books_book_authors_id" ON "books_book_authors" ("book_id");
CREATE INDEX "books_book_authors_id" ON "books_book_authors" ("author_id");
CREATE INDEX "books_book_id" ON "books_book" ("publisher_id");
COMMIT;
7.พิม python manage.py syncdb ใน Terminal เพื่อให้ Django สร้างไฟล์ Database ออกมาให้เราเอง
7.1 เมื่อพิมไปแล้วระหว่างนั้นจะมีการถามให้เราสร้าง Super user ไหมให้เราตกลงจากนั้นใส่ username, password, e-mail ของตนเองเข้าไป
8.ทดลองการสร้างข้อมูลใส่ใน Database ผ่าน shell
>>> from books.models import Publisherจากตัวอย่างเป็นการสร้าง Object จาก Publisher โดยหากเราไม่เรียกคำสั่ง p1.save() และ p2.save() เมื่อเราปิด Shell ไปนั้นใน Database ของเราก็จะยังไม่มี p1 และ p2 อยู่ในนั้นถือเป็นข้อกำหนด แต่ถ้าหากเราต้องการให้สร้างแล้วบันทึกลงใน Database ทันทีไม่ต้องมาพิม save() เองอีกรอบก็สามารถทำได้ด้วยคำสั่งนี้
>>> p1 = Publisher(name=’Apress’, address=’2855 Telegraph Avenue’,
... city=’Berkeley’, state_province=’CA’, country=’U.S.A.’,
... website=’http://www.apress.com/’)
>>> p1.save()
>>> p2 = Publisher(name="O’Reilly", address=’10 Fawcett St.’,
... city=’Cambridge’, state_province=’MA’, country=’U.S.A.’,
... website=’http://www.oreilly.com/’)
>>> p2.save()
>>> publisher_list = Publisher.objects.all()
>>> publisher_list
[<Publisher: Publisher object>, <Publisher: Publisher object>]
>>> p1 = Publisher.objects.create(name=’Apress’,เมื่อพิมคำสั่งนี้จะเป็นการสร้าง object ขึ้นพร้อมกับ save ลง Database ของเราทันที
... address=’2855 Telegraph Avenue’,
... city=’Berkeley’, state_province=’CA’, country=’U.S.A.’,
... website=’http://www.apress.com/’)
9.จากข้อ 8 ที่ผ่านมาตอนเรียก publisher_list เพื่อแสดงข้อมูลนั้นปรากฎว่าได้ผลดังนี้
[<Publisher: Publisher object>, <Publisher: Publisher object>]ซึ่งเราไม่สามารถรู้ได้เลยว่า object ที่แสดงอยู่อันไหนเป็นอันไหนเพราะเหมือนกันหมดดังนั้นเพื่อการแสดงผลที่ถูกต้องให้เราเข้าไปแก้ไขไฟล์ models.py ใน books อีกครั้งโดยการเพิ่ม method __unicode__() เข้าไปจะได้ผลดังนี้
from django.db import modelsโดย __unicode__(self) ใน Publisher เป็นการส่ง name กลับไปแสดงผล ดังนั้นเมื่อเรียก publisher_list อีกครั้งจะแสดงผลได้แบบนี้
class Publisher(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=50)
city = models.CharField(max_length=60)
state_province = models.CharField(max_length=30)
country = models.CharField(max_length=50)
website = models.URLField()
def __unicode__(self):
return self.name
class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField()
def __unicode__(self):
return u'%s %s' % (self.first_name, self.last_name)
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
publication_date = models.DateField()
def __unicode__(self):
return self.title
[<Publisher: Apress>, <Publisher: O’Reilly>]หากเราเรียกของ Author ก็จะได้เป็นชื่อ first_name last_name ไปแสดงผลแทน ส่วนของ book ก็จะได้เป็น title ไปแสดงผลเช่นกัน
โดยข้อแม้ของการใช้ __unicode__(self) คือข้อมูลที่ return ไปต้องเป็นรูปแบบ unicode เท่านั้นเช่น String เป็นต้นหากส่ง int ไปจะเกิด Error ขึ้น
10.การแก้ไขเปลี่ยนแปลงค่าใน Database ผ่าน shell หากเราต้องการเปลี่ยนแปลงค่าใน p1 ที่สร้างไว้ในข้อ 8 เราสามารถใช้คำสั่งนี้ในการเปลี่ยนค่าได้เลย
>>> p1.name = ’Apress Publishing’11.การ filter objects ใน shell
>>> p1.save()
>>> Publisher.objects.filter(name=’Apress’)จากการ filter ทั้ง 3 แบบนั้นเราสามารถใส่เงื่อนไขเพื่อเลือก object ออกมาแสดงได้ตามต้องการโดยแบบที่ 1 และ 2 นั้นจะดึงเฉพาะ object ที่มีเงื่อนไขตามในวงเล็บเท่านั้น ใส่เงื่อนไขกี่ตัวก็ได้แต่ในแบบที่ 3 จะแตกต่างจากแบบที่ 1 และ 2 ตรงที่จะดึงเอา object ออกมาในกรณีที่ name มี press อยู่ในนั้นหมายความว่าถ้ามี 2 object ที่เป็น Apress และ Bpress ก็จะได้คำตอบออกมาเป็นทั้ง Apress และ Bpress นั่นเอง
[<Publisher: Apress>]
>>> Publisher.objects.filter(country="U.S.A.", state_province="CA")
[<Publisher: Apress>]
>>> Publisher.objects.filter(name__contains="press")
[<Publisher: Apress>]
12.การดึงค่า object ออกมาเพียง 1 ตัว
>>> Publisher.objects.get(name="Apress")การใช้ get นั้นในแบบที่ 1 และ 3 จะแตกต่างกันที่หาก get แล้วมี object ที่ name ตรงกันก็จะได้ object นั้นออกมาในแบบแรก แต่ในแบบที่ 3 จะเห็นว่าเกิด error ขึ้นเนื่องจากไม่สามารถ get object ออกมาได้เนื่องจากไม่มี object ไหนที่ name เป็น Penguin เลยแต่ในแบบที่ 2 เกิด error เพราะ get object ออกมาได้ แต่ได้มา 2 ตัวซึ่งเงื่อนไขของ get คือต้องได้กลับมาเพียง 1 ตัวดังนั้นจึงเกิด error ขึ้น
<Publisher: Apress>
>>> Publisher.objects.get(country="U.S.A.")
Traceback (most recent call last):
...
MultipleObjectsReturned: get() returned more than one Publisher --
it returned 2! Lookup parameters were {’country’: ’U.S.A.’}
>>> Publisher.objects.get(name="Penguin")
Traceback (most recent call last):
...
DoesNotExist: Publisher matching query does not exist.
13.การ sort object ที่นำออกมาแสดงผล
>>> Publisher.objects.order_by("name")ในแบบที่ 1, 2 และ 3 นั้นคือการเรียกตามตัวแปรที่เรากำหนดจากก่อนไปหลังของตัวแปรที่อยู่ในวงเล็บของ order_by() แบบที่ 4 ก็เช่นกันเพียงแต่เรียง 2 ครั้งโดยเรียงตาม state_province เป็นหลัก ในแบบที่ 5 นั้นหากเราใส่ - ไปข้างหน้า name แบบนั้นก็จะทำให้เรียงลำดับกลับกันจากเดิม ก่อนไปหลัง เป็น หลังไปก่อน กลับด้านกันนั่นเอง
[<Publisher: Apress>, <Publisher: O’Reilly>]
>>> Publisher.objects.order_by("address")
[<Publisher: O’Reilly>, <Publisher: Apress>]
>>> Publisher.objects.order_by("state_province")
[<Publisher: Apress>, <Publisher: O’Reilly>]
>>> Publisher.objects.order_by("state_province", "address")
[<Publisher: Apress>, <Publisher: O’Reilly>]
>>> Publisher.objects.order_by("-name")
[<Publisher: O’Reilly>, <Publisher: Apress>]
13.1 เราสามารถ sort ลำดับของ object ทุกรอบได้โดยที่ไม่ต้องมาพิมคำสั่ง order_by ทุกครั้งด้วยการใช้ Class Meta โดยการเพิ่ม Class นี้ไว้เป็น Class ย่อยของตัวที่เราต้องให้ sort ดังนั้นลองใส่ไปใน Class Publisher
class Meta:ซึ่งทุก Class ใน models นั้นสามารถใส่ Meta เข้าไปได้ทั้งหมดและ Meta นั้นทำได้มากกว่าเพียงการ sort อีกด้วยในตัวอย่างจะเป็นการ sort ตามชื่อ โดยเรายังสามารถใส่เป็น -name ก็จะให้ค่าแบบที่เราพิมใน shell แบบที่ 5 อีกด้วยซึ่งเมื่อเรียก Publisher.objects.all() ก็จะแสดง List ที่ sort ลำดับของ object มาให้ตามใน ordering ที่เราเขียนใน Meta ไว้
ordering = [’name’]
14.การลบ object ออกจาก Database
>>> p = Publisher.objects.get(name="O’Reilly")การลบเมื่อเราเลือก object ที่ต้องการลบได้แล้วนั้นก็ใช่คำสั่ง delete() ลบได้เลยแบบในช่วงแรกซึ่ง p.delete() จะลบออกจาก Database ทันทีหลังจากรันคำสั่ง และถ้าหากเราไม่ต้องการลบทีละตัวก็สามารถใช้การ filter หรือ เรียกทั้งหมดมาจาก all แล้วลบพร้อมกันทั้งหมดก็ได้เช่นกัน
>>> p.delete()
>>> Publisher.objects.all()
[<Publisher: Apress Publishing>]
>>> Publisher.objects.filter(country=’USA’).delete()
>>> Publisher.objects.all().delete()
>>> Publisher.objects.all()
[]
จาก Chapter 5 นั้นเราได้เรียนรู้การใช้ Models ผ่าน Django book ซึ่ง models นั้นช่วยให้อำนวยความสะดวกในการแก้ไข เพิ่ม ลบ ไฟล์ใน Database ได้อย่างง่ายดายซึ่งถือเป็นข้อดีและยังช่วยลดเวลาในการจัดการกับ Database ของเราลงไปอีกด้วย
ภาพตัวอย่างโค้ดใน models ที่แก้ไขจนจบ
ไม่มีความคิดเห็น:
แสดงความคิดเห็น