วันพุธที่ 29 มกราคม พ.ศ. 2557

Django Book Chapter 6 : The Django Admin Site

    จาก Chapter 5 นั้นหากเราต้องการจะแก้ไขข้อมูลใน Database เราต้องเข้าไปผ่าน shell ซึ่งยุ่งยากและต้องจำคำสั่งดังนั้นเพื่อให้ง่ายต่อการเพิ่ม ลบ แก้ไข ข้อมูลนั้นหน้า Admin จึงเกิดขึ้นในบทนี้จะกล่าวถึงการจัดการและการใช้หน้า Admin

1.ใน Django เวอร์ชั่น 1.6 นั้นหน้า admin ถูกเปิดไว้อยู่แล้วเป็นค่าพื้นฐานดังนั้นจึงไม่ต้องแก้ไขอะไรเพื่อให้สามารถใช้งานหน้า admin เลยทันทีดังนั้นพิมคำสั่ง python manage.py runserver เพื่อเปิด Server จากนั้น เข้าไปที่หน้า http://127.0.0.1:8000/admin/ ผ่าน Browser ของเรา

2.เมื่อเข้าไปแล้วจะเจอหน้าให้ Log in ให้เราใส่ Username และ Password ที่เราได้ตั้งไว้ต้องสร้าง Superuser ใน Chapter 5 ที่ผ่านมาแต่ถ้าหากใครที่ใน Chapter 5 ยังไม่ได้สร้าง Superuser นั้นให้พิมคำสั่ง python manage.py createsuperuser ใน Terminal เพื่อสร้าง Superuser แล้ว log in เข้าระบบ admin ไป

ภาพตัวอย่างหน้า http://127.0.0.1:8000/admin/


ภาพตัวอย่างเมื่อ Log in เข้าไปแล้วด้วย Superuser


3.จะเห็นว่าเมื่อ Log in เข้าไปแล้วเราสามารถเข้าไปแก้ไขข้อมูลของ User เพิ่มลบ ได้ตามต้องการในหัวข้อ Users ทดลองเล่นได้ครับและยังมี History ให้เราดูอีกด้วยว่ามีการแก้ไขอะไรเกี่ยวกับ User ไหนไปบ้าง เมื่อวันไหนแก้ไขอะไร



4.ทำการเพิ่ม Models ของเราที่สร้างไว้ใน Chapter 5 มาใส่ใน admin เพื่อให้เราสามารถแก้ไขได้โดยเปิดไฟล์ books/admin.py แล้วแก้ไขดังนี้
from django.contrib import admin
from books.models import Publisher, Author, Book

admin.site.register(Publisher)
admin.site.register(Author)
admin.site.register(Book)
แล้วลองรีเฟรชหน้า admin ใหม่จะเห็น Class ใน models ของเราปรากฎอยู่ในหน้า admin แล้ว


    การทำงานของ admin เบื้องต้นนั้นเมื่อเราเริ่ม runserver ตัว Django จะอ่านค่าจากใน Urls.py ซึ่งเมื่อเจอ admin.autodiscover() เป็นบรรทัดที่บอกให้ admin เริ่มทำงานดังนั้นก็จะไปอ่านค่าจากใน INSTALLED_APPS สำหรับ Setting ของ admin และจากนั้นจึงไปหาไฟล์ admin.py ซึ่งเมื่อเจอก็จะโหลดโค้ดภายในไฟล์ไปใส่ในเว็บ admin ด้วยดังนั้นเมื่อเราแก้ไขเพื่อเพิ่ม models ใน admin.py จึงทำให้เราเห็น models ทั้ง 3 มาโผล่อยู่ในเว็บ admin นั่นเอง

5.เพิ่มทางเลือกให้กับ Author ใน admin โดยปกตินั้นหากเราเข้าไปเพิ่ม Author ใน admin นั้นเราจำเป็นต้องกรอก ข้อมูลทั้งหมด 3 อย่างคือ First name, Last name, E-mail ซึ่ง E-mail นั้นบางคนก็ไม่ได้ระบุมาให้ในหนังสือ ซึ่งถ้าเราไม่ใส่ E-mail เราก็ Save ข้อมูลลงใน Database ไม่ได้ดังนั้นเพื่อให้เราไม่จำเป็นต้องใส่ E-mail ก็สามารถใส่ค่าแล้ว Save ลงใน Database ได้ให้เข้าไปแก้ models.py ใน books อีกครั้งจากเดิม Author เรามีหน้าตาประมาณนี้
class Author(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=40)
    email = models.EmailField()
ให้เราแก้ไขในส่วนของ email ให้เป็นดังนี้
class Author(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=40)
    email = models.EmailField(blank=True)
จากที่แก้ไปเมื่อสักครู่นั้นเป็นการบอกว่าหากจะสร้าง Object ของ Author นั้นในส่วนของ email นั้นหากไม่ใส่ค่ามาก็สามารถสร้าง Object ได้นั่นเอง

6.จากข้อ 5 การใส่ blank=True สามารถใส่ได้ในทุกๆ Field เพื่อให้ Admin ไม่ต้องถูกบังคับว่าต้องใส่ค่าถึงจะเพิ่มข้อมูลได้แต่ก็มี Field บางแบบที่ใส่ไม่ได้เช่น DateField, TimeField,
DateTimeField, IntegerField, DecimalField, FloatField เป็นต้น ซึ่งเมื่อเราไม่ใส่ค่าลงใน Field ใดๆก็ตามหากเราปล่อยว่างไว้ Field เหล่านั้นจะถูกกำหนดค่าให้เป็น Empty String เองโดยอัตโนมัติ แต่ Field ในตัวอย่างเบื้องต้นนั้นไม่สามารถใส่ได้เพราะมี Data Type ที่ถูกระบุไว้อยู่แล้วเช่น IntegerField ถูกระบุว่าต้องใส่ int ไว้อยู่แล้วเมื่อใส่ Empty String เข้าจึงเกิด Error ขึ้น วิธีการแก้ก็คือนอกจากเราจะใส่ blank เข้าไปแล้วยังมีอีกตัวที่ต้องใส่เข้าไปด้วยคือ null เพื่อให้เมื่อไม่ใส่ค่าก็จะให้ตัวแปรนั้นเป็น null ไปโดยจะแก้ไขใน publication_date ของ Book ดังนี้
class Book(models.Model):
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField(Author)
    publisher = models.ForeignKey(Publisher)
    publication_date = models.DateField(blank=True, null=True)
โดยเมื่อแก้ไขเสร็จแล้วต้อง Update Table ใน Database ใหม่ด้วย

7.เมื่อเราเข้าไปเพิ่ม Book, Author, Publisher นั้นจะมีช่องให้กรอกข้อมูลต่างๆ ซึ่งชื่อที่ใช้ระบุว่าช่องที่กรอกคือข้อมูลของอะไรจะกำหนดมาให้โดยอัตโนมัติจากชื่อตัวแปรที่เราตั้งไว้ใน models.py แต่ถ้าหากเราต้องการตั้งเองโดยอิสระก็สามารถทำได้โดยการเพิ่ม verbose_name เข้าไปดังนี้
class Author(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=40)
    email = models.EmailField(blank=True, verbose_name='e-mail')
ภาพตัวอย่างก่อนเพิ่ม verbose_name


ภาพตัวอย่างหลังเพิ่ม verbose_name


8.หากเรามีข้อมูลใน Database แล้วนั้นจะพบว่าการแสดงชื่อของข้อมูลนั้นจะแสดงตาม __unicode__ ที่เราเขียนไว้ใน models ดังนั้นเพื่อความสวยงามและให้ง่ายต่อการอ่านข้อมูล เราสามารถตั้งค่าได้เองโดยเพิ่ม Class เข้าไปใน admin.py และแก้ไขดังนี้
from django.contrib import admin
from books.models import Publisher, Author, Book

class AuthorAdmin(admin.ModelAdmin):
    list_display = ('first_name', 'last_name', 'email')
    search_fields = ('first_name', 'last_name')

class BookAdmin(admin.ModelAdmin):
    list_display = ('title', 'publisher', 'publication_date')
    list_filter = ('publication_date',)
    date_hierarchy = 'publication_date'
    ordering = ('-publication_date',)

admin.site.register(Publisher)
admin.site.register(Author, AuthorAdmin)
admin.site.register(Book, BookAdmin)
    โดย list_display เป็นการแบ่งช่องข้อมูลที่จะแสดงออกมาตามลำดับใน tuple นั้นจากตัวอย่าง first_name จะอยู่ซ้ายสุดตามด้วย last_name และ email ส่วน search_fields จะเป็นการเพิ่มช่อง search โดยข้อความที่พิมไปในช่องจะค้นหาจากข้อมูลที่ระบุไว้ใน tuple เท่านั้น list_filter คือการเพิ่ม filter เข้าไปในหน้าแอดมินช่วยให้สามารถ filter ข้อมูลได้ง่ายขึ้นโดยข้อมูลที่ใช้ในการ filter มาจาก publication_date ของ Book ทุกเล่ม date_hierarchy จะเพิ่มเมนูขึ้นมาให้กดเลือกซึ่งเป็น filter อีกเช่นกันแต่จะเป็น filter จากวันที่เท่านั้น ordering จะเป็นการกำหนดการเรียงลำดับข้อมูลที่แสดงผลมาให้ทันทีโดยในตัวอย่างจะเรียงจากวันที่เก่ากว่าขึ้นก่อน

ภาพตัวอย่างหน้า admin ของ Author


ภาพตัวอย่างหน้า admin ของ Book


9.นอกจากเราจะสามารถจัดรูปแบบการแสดงผลในหน้า admin ได้เองแล้วเรายังสามารถจัดรูปแบบตอนแก้ไขข้อมูลหรือเพิ่มข้อมูลได้อีกด้วยเข้าไปแก้ในไฟล์ admin.py ดังนี้
class BookAdmin(admin.ModelAdmin):
    list_display = (’title’, ’publisher’, ’publication_date’)
    list_filter = (’publication_date’,)
    date_hierarchy = ’publication_date’
    ordering = (’-publication_date’,)
    filter_horizontal = (’authors’,)
    raw_id_fields = (’publisher’,)
    โดย filter_horizontal เป็นการเปลี่ยนรูปแบบการเลือกให้กลายเป็นหน้าต่าง 2 ฝั่งเป็นฝั่งที่เลือกกับไม่ได้เลือก ซึ่งเดิมๆหากเราต้องการจะเลือก authors หลายๆคนต้องกด Control ค้างแล้วคลิ๊กเพิ่ม แต่ในแบบนี้เราแค่ดับเบิ้ลคลิ๊กชื่อ ก็จะถูกเลือกทันทีเพิ่มความสะดวกมากขึ้น ส่วน raw_id_fields เป็นการเปลี่ยนจากเดิมจะให้เราเลือกโดยใช้ชื่อเป็นตัวกำหนดแต่เมื่อกำหนดตัวนี้ขึ้นมานั้นจะใช้ id เป็นตัวเลือกแทนแต่เราก็สามารถกดดูชื่อเต็มๆได้เช่นเดิม


    จาก Chapter 6 นั้นหน้า Admin นั้นมีประโยชน์ในการช่วยจัดการกับ Database ของเราผ่านหน้าเว็บซึ่งง่ายกว่าการพิมคำสั่งผ่าน Shell อย่างแน่นอนและนอกจากจะช่วยให้จัดการง่ายขึ้นเรายังสามารถปรับเปลี่ยนรูปแบบการแสดงผลหรือการแก้ไขข้อมูลได้ตามใจเราต้องการอีกด้วย
Read more ...

วันอังคารที่ 28 มกราคม พ.ศ. 2557

Django Book Chapter 5 : Models

    จาก Chapter 4 เราได้เรียนรู้เกี่ยวกับใช้ Templates ใน Django ไปแล้วดังนั้นในบทที่ 5 จะเริ่มเข้าสู่การพัฒนา Web Application โดยใช้ Models และหากมีการใช้ Database เราก็สามารถจัดการ Database ในรูปแบบของ Views ที่เราทำมาใน Chapter 4 ก็สามารถทำได้แต่จะมีความยุ่งยากซับซ้อนในการเขียนมาก ดังนั้นเพื่อให้ง่ายต่อการพัฒนาเราจึงใช้ Models ของ Django มาช่วย

1.รูปแบบของ Database ที่เลือกใช้นั้นจะเป็นของ sqlite3 ซึ่งมีอยู่แล้วใน Django จึงไม่ต้องทำการแก้ไขหรือตั้งค่าอะไรเพิ่มเติม แต่หากอยากใช้ Database ตัวอื่นศึกษาเพิ่มเติมได้ที่นี่ คลิก

2.เริ่มสร้าง Model โดยการพิม python manage.py startapp ชื่อแอพ ใน Terminal ในตัวอย่างจะใช้ books
python manage.py startapp books
ซึ่งจะได้โฟลเดอร์ใหม่ขึ้นมาชื่อ books และมีโครงสร้างภายในดังนี้
books/
    admin.py
    __init__.py
    models.py
    tests.py
    views.py
3.เปิดไฟล์ models.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):
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField(Author)
    publisher = models.ForeignKey(Publisher)
    publication_date = models.DateField()
    จากโค้ดที่แก้ไขนั้นได้ import models จาก django.db มาซึ่งเป็น API พื้นฐานที่มากับ Django เป็นโครงร่างของ Class Models ที่ให้เรานำมาใช้งานได้ซึ่งในตัวอย่างนี้แบ่งออกเป็นหลักๆ 3 Class ใหญ่คือ Publisher, Author, Book

    ซึ่งใน 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 = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'books',
)
5.จากนั้นลองพิม python manage.py validate ใน Terminal หากเราทำทุกอย่างถูกต้องได้ Output กลับมาเป็น 0 errors found แต่หากมี error ให้ลองเช็คใน models.py ว่ามีส่วนไหนที่ผิดหรือไม่จากนั้นแก้ไขจนเสร็จแล้วลองพิมคำสั่งอีกครั้งหากยังมี error ก็ให้แก้ไปเรื่อยๆจนกว่าจะได้เป็น 0 errors found

    ซึ่ง validate เป็นการเช็คว่า models ที่เราเขียนขึ้นมานั้นมีส่วนไหนที่ syntax และ logic ผิดหรือไม่หากไม่ผิดก็จะได้ 0 errors found แต่หากมีที่ผิดก็จะฟ้อง error ขึ้นมาซึ่งเป็นตัวช่วยในการตรวจสอบว่า models ที่เราเขียนนั้นมีความถูกต้องมากน้อยเพียงใดนั่นเอง

6.จากนั้นพิม python manage.py sqlall books เพื่อให้ Django สร้างแบบฟอร์มของ Table สำหรับการใช้ในการสร้าง Database ขึ้นมาซึ่งจะได้หน้าตาประมาณนี้
BEGIN;
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;  
ซึ่งการใช้ sqlall books ยังไม่ใช่การสร้าง Database แต่เป็นเพียงการสร้างฟอร์มซึ่งเราสามารถนำโค้ดข้างบนไปใส่ใน Database เองก็ได้หรือจะทำตามข้อต่อไปนี้

7.พิม python manage.py syncdb ใน Terminal เพื่อให้ Django สร้างไฟล์ Database ออกมาให้เราเอง

7.1 เมื่อพิมไปแล้วระหว่างนั้นจะมีการถามให้เราสร้าง Super user ไหมให้เราตกลงจากนั้นใส่ username, password, e-mail ของตนเองเข้าไป

8.ทดลองการสร้างข้อมูลใส่ใน Database ผ่าน shell
>>> from books.models import Publisher
>>> 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>]
จากตัวอย่างเป็นการสร้าง Object จาก Publisher โดยหากเราไม่เรียกคำสั่ง p1.save() และ p2.save() เมื่อเราปิด Shell ไปนั้นใน Database ของเราก็จะยังไม่มี p1 และ p2 อยู่ในนั้นถือเป็นข้อกำหนด แต่ถ้าหากเราต้องการให้สร้างแล้วบันทึกลงใน Database ทันทีไม่ต้องมาพิม save() เองอีกรอบก็สามารถทำได้ด้วยคำสั่งนี้
>>> p1 = Publisher.objects.create(name=’Apress’,
...            address=’2855 Telegraph Avenue’,
...            city=’Berkeley’, state_province=’CA’, country=’U.S.A.’,
...            website=’http://www.apress.com/’)
เมื่อพิมคำสั่งนี้จะเป็นการสร้าง object ขึ้นพร้อมกับ save ลง Database ของเราทันที

9.จากข้อ 8 ที่ผ่านมาตอนเรียก publisher_list เพื่อแสดงข้อมูลนั้นปรากฎว่าได้ผลดังนี้
[<Publisher: Publisher object>, <Publisher: Publisher object>]
    ซึ่งเราไม่สามารถรู้ได้เลยว่า object ที่แสดงอยู่อันไหนเป็นอันไหนเพราะเหมือนกันหมดดังนั้นเพื่อการแสดงผลที่ถูกต้องให้เราเข้าไปแก้ไขไฟล์ models.py ใน books อีกครั้งโดยการเพิ่ม method __unicode__() เข้าไปจะได้ผลดังนี้
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()
   
    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
    โดย __unicode__(self) ใน Publisher เป็นการส่ง name กลับไปแสดงผล ดังนั้นเมื่อเรียก publisher_list อีกครั้งจะแสดงผลได้แบบนี้
[<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’
>>> p1.save()
11.การ filter objects ใน shell
>>> Publisher.objects.filter(name=’Apress’)
[<Publisher: Apress>]
>>> Publisher.objects.filter(country="U.S.A.", state_province="CA")
[<Publisher: Apress>]
>>> Publisher.objects.filter(name__contains="press")
[<Publisher: Apress>]
    จากการ filter ทั้ง 3 แบบนั้นเราสามารถใส่เงื่อนไขเพื่อเลือก object ออกมาแสดงได้ตามต้องการโดยแบบที่ 1 และ 2 นั้นจะดึงเฉพาะ object ที่มีเงื่อนไขตามในวงเล็บเท่านั้น ใส่เงื่อนไขกี่ตัวก็ได้แต่ในแบบที่ 3 จะแตกต่างจากแบบที่ 1 และ 2 ตรงที่จะดึงเอา object ออกมาในกรณีที่ name มี press อยู่ในนั้นหมายความว่าถ้ามี 2 object ที่เป็น Apress และ Bpress ก็จะได้คำตอบออกมาเป็นทั้ง Apress และ Bpress นั่นเอง

12.การดึงค่า object ออกมาเพียง 1 ตัว
>>> Publisher.objects.get(name="Apress")
<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.
    การใช้ get นั้นในแบบที่ 1 และ 3 จะแตกต่างกันที่หาก get แล้วมี object ที่ name ตรงกันก็จะได้ object นั้นออกมาในแบบแรก แต่ในแบบที่ 3 จะเห็นว่าเกิด error ขึ้นเนื่องจากไม่สามารถ get object ออกมาได้เนื่องจากไม่มี object ไหนที่ name เป็น Penguin เลยแต่ในแบบที่ 2 เกิด error เพราะ get object ออกมาได้ แต่ได้มา 2 ตัวซึ่งเงื่อนไขของ get คือต้องได้กลับมาเพียง 1 ตัวดังนั้นจึงเกิด error ขึ้น

13.การ sort object ที่นำออกมาแสดงผล
>>> Publisher.objects.order_by("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>]
    ในแบบที่ 1, 2 และ 3 นั้นคือการเรียกตามตัวแปรที่เรากำหนดจากก่อนไปหลังของตัวแปรที่อยู่ในวงเล็บของ order_by() แบบที่ 4 ก็เช่นกันเพียงแต่เรียง 2 ครั้งโดยเรียงตาม state_province เป็นหลัก ในแบบที่ 5 นั้นหากเราใส่ - ไปข้างหน้า name แบบนั้นก็จะทำให้เรียงลำดับกลับกันจากเดิม ก่อนไปหลัง เป็น หลังไปก่อน กลับด้านกันนั่นเอง

13.1 เราสามารถ sort ลำดับของ object ทุกรอบได้โดยที่ไม่ต้องมาพิมคำสั่ง order_by ทุกครั้งด้วยการใช้ Class Meta โดยการเพิ่ม Class นี้ไว้เป็น Class ย่อยของตัวที่เราต้องให้ sort ดังนั้นลองใส่ไปใน Class Publisher
class Meta:
    ordering = [’name’]
ซึ่งทุก Class ใน models นั้นสามารถใส่ Meta เข้าไปได้ทั้งหมดและ Meta นั้นทำได้มากกว่าเพียงการ sort อีกด้วยในตัวอย่างจะเป็นการ sort ตามชื่อ โดยเรายังสามารถใส่เป็น -name ก็จะให้ค่าแบบที่เราพิมใน shell แบบที่ 5 อีกด้วยซึ่งเมื่อเรียก Publisher.objects.all() ก็จะแสดง List ที่ sort ลำดับของ object มาให้ตามใน ordering ที่เราเขียนใน Meta ไว้

14.การลบ object ออกจาก Database
>>> p = Publisher.objects.get(name="O’Reilly")
>>> p.delete()
>>> Publisher.objects.all()
[<Publisher: Apress Publishing>]
>>> Publisher.objects.filter(country=’USA’).delete()
>>> Publisher.objects.all().delete()
>>> Publisher.objects.all()
[]
    การลบเมื่อเราเลือก object ที่ต้องการลบได้แล้วนั้นก็ใช่คำสั่ง delete() ลบได้เลยแบบในช่วงแรกซึ่ง p.delete() จะลบออกจาก Database ทันทีหลังจากรันคำสั่ง และถ้าหากเราไม่ต้องการลบทีละตัวก็สามารถใช้การ filter หรือ เรียกทั้งหมดมาจาก all แล้วลบพร้อมกันทั้งหมดก็ได้เช่นกัน

    จาก Chapter 5 นั้นเราได้เรียนรู้การใช้ Models ผ่าน Django book ซึ่ง models นั้นช่วยให้อำนวยความสะดวกในการแก้ไข เพิ่ม ลบ ไฟล์ใน Database ได้อย่างง่ายดายซึ่งถือเป็นข้อดีและยังช่วยลดเวลาในการจัดการกับ Database ของเราลงไปอีกด้วย

ภาพตัวอย่างโค้ดใน models ที่แก้ไขจนจบ

Read more ...

วันอังคารที่ 21 มกราคม พ.ศ. 2557

Django Book Chapter 4 : Templates

    จาก Chapter 3 เราได้เรียนรู้ในเรื่องของการใช้ Views และ Urls ไปแล้วแต่ใน Views ของเรานั้นจะมีโค้ด HTML ผสมอยู่บ้างบางส่วนแต่หากหน้าเว็บของเราจำเป็นต้องมีโค้ด HTML ยาวๆไฟล์ Views ของเราก็จะอ่านยากแล้วทำให้ยากต่อการแก้ไขหรือทบทวนสิ่งที่เขียนไว้ได้ จึงเกิด Templates ขึ้นมาเพื่อแยกส่วนระหว่างโค้ด HTML และโค้ด Python ออกจากกันเพื่อให้ง่ายต่อการอ่านและสามารถนำโค้ด HTML นั้นกลับมาใช้ใหม่ได้อีกด้วย

1.ทดลองการใช้ Templates ใน shell ดังต่อไปนี้

1.1 ตัวอย่างที่ 1
>>> from django import template
>>> t = template.Template(’My name is {{ name }}.’)
>>> c = template.Context({’name’: ’Adrian’})
>>> print t.render(c)
My name is Adrian.
>>> c = template.Context({’name’: ’Fred’})
>>> print t.render(c)
My name is Fred.
    จากตัวอย่างนี้จะเป็นการ import API template ของ Django มาใช้ โดยให้ t เป็น template ที่เราสร้างขึ้นแบบง่ายๆ จะสังเกตเห็นว่า name นั้นมี {{ }} ครอบอยู่ ซึ่งนั่นเป็น Object ที่เราต้อง Context ไปใส่ใน Template เพื่อใช้ในการแสดงผล ต่อมาจะเห็นว่า c เป็นตัวแปรที่กำหนดค่า name ให้เป็น Adrian เก็บไว้จากนั้นจึงนำ c ไป render ใส่ t หรือก็คือการนำ name ที่เก็บไว้ใน c ไปใส่ให้ name ใน t ที่รอค่ามาใส่อยู่นั่นเองจึึงทำให้ผลเมื่อ Print ออกมาเป็น My name is Adrian. อย่างที่บอกไว้ข้างต้นนั้นว่า Template สามารถนำมาใช้ใหม่ได้ หากตัวแปร c ของเรานั้นไม่ได้ Context เป็นชื่อ Adrian แต่เปลี่ยนเป็น Fred เมื่อเรานำมา render ใหม่จากค่าที่เป็น Adrian ก็จะเปลี่ยนแปลงเป็น Fred ตามค่าของตัวแปร name ใน Context ที่เรา render เข้าไป

1.2 ตัวอย่างที่ 2
>>> from django.template import Template
>>> t = Template(’{% notatag %}’)
Traceback (most recent call last):
    File "<stdin>", line 1, in ?
    ...
django.template.TemplateSyntaxError: Invalid block tag: ’notatag’
    จากตัวอย่างนี้จะเป็นการใช้ tag ใน template ซึ่ง tag ที่นำมาใช้นั้นไม่มีอยู่จึงเกิด Error ขึ้นแบบนี้ ซึ่งการเกิด Error แบบนี้เป็นได้หลายกรณีเช่น เป็น tag ที่ไม่มีอยู่จริง, เป็น filters ที่ไม่มีอยู่จริง, ลืมใส่ tag ปิด (tag บางตัวต้องมี tag ปิดด้วย) เป็นต้น

1.3 ตัวอย่างที่ 3
>>> from django.template import Template, Context
>>> raw_template = """<p>Dear {{ person_name }},</p>
...
... <p>Thanks for placing an order from {{ company }}. It’s scheduled to
... ship on {{ ship_date|date:"F j, Y" }}.</p>
...
... {% if ordered_warranty %}
... <p>Your warranty information will be included in the packaging.</p>
... {% else %}
... <p>You didn’t order a warranty, so you’re on your own when
... the products inevitably stop working.</p>
... {% endif %}
...
... <p>Sincerely,<br />{{ company }}</p>"""
>>> t = Template(raw_template)
>>> import datetime
>>> c = Context({’person_name’: ’John Smith’,
...            ’company’: ’Outdoor Equipment’,
...            ’ship_date’: datetime.date(2009, 4, 2),
...            ’ordered_warranty’: False})
>>> t.render(c)
u"<p>Dear John Smith,</p>\n\n<p>Thanks for placing an order from Outdoor
Equipment. It’s scheduled to\nship on April 2, 2009.</p>\n\n\n<p>You
didn’t order a warranty, so you’re on your own when\nthe products
inevitably stop working.</p>\n\n\n<p>Sincerely,<br />Outdoor Equipment
</p>"
    จากตัวอย่างสังเกตว่าจะมี {{ ship_date|date:"F j, Y" }} ซึ่งใน tag นี้มี filter ที่ชื่อ date ด้วยซึ่งเอาไว้จัดรูปแบบในการแสดงผลของวันจากตัวอย่างจะเห็นว่าผลลัพธ์ที่ออกมาจะเป็น เดือน วัน, ปี และยังมี tag if ซึ่งใช้หลักการเดียวกับการเขียน if else ในโปรแกรมทั่วไปซึ่งตัวแปรที่ใช้เช็ค True False คือ ordered_warranty นั่นเองซึ่งหากเป็น True ก็จะใส่ <p>Your warranty information will be included in the packaging.</p> ลงในผลลัพธ์ที่ได้จากการ render แต่ถ้าเป็น False ก็จะใส่ <p>You didn’t order a warranty, so you’re on your own when the products inevitably stop working.</p> ลงในผลลัพธ์แทน

1.4 ตัวอย่างที่ 4
>>> from django.template import Template, Context
>>> class Person(object):
...          def __init__(self, first_name, last_name):
...              self.first_name, self.last_name = first_name, last_name
>>> t = Template(’Hello, {{ person.first_name }} {{ person.last_name }}.’)
>>> c = Context({’person’: Person(’John’, ’Smith’)})
>>> t.render(c)
u’Hello, John Smith.’
    จากตัวอย่างนี้แสดงให้เห็นว่าหาก Object ที่เรา Context ไปยัง Template เป็น Object ใหญ่ที่มีตัวแปรต่างๆอยู่ภายใน เราสามารถดึงค่าเหล่านั้นมาใช้ได้โดยการพิมชื่อของ Object ตามด้วย "." แล้วตามด้วยชื่อตัวแปรที่ต้องการดังตัวอย่างข้างบนนี้

1.5 ตัวอย่างที่ 5
>>> from django.template import Template, Context
>>> t = Template(’{{ var }} -- {{ var.upper }} -- {{ var.isdigit }}’)
>>> t.render(Context({’var’: ’hello’}))
u’hello -- HELLO -- False’
>>> t.render(Context({’var’: ’123’}))
u’123 -- 123 -- True’
    จากตัวอย่างนี้นอกจากจะสามารถดึงตัวแปรที่อยู่ภายใน Object ได้แล้วจากตัวอย่างที่ 1.4 Templates ก็ยังสามารถเรียกใช้ Method ของ Object นั้นๆได้อีกด้วยเช่นกันเห็นได้จากตัวอย่างนี้

1.6 ตัวอย่างที่ 6
>>> from django.template import Template, Context
>>> t = Template(’Your name is {{ name }}.’)
>>> t.render(Context())
u’Your name is .’
>>> t.render(Context({’var’: ’hello’}))
u’Your name is .’
>>> t.render(Context({’NAME’: ’hello’}))
u’Your name is .’
>>> t.render(Context({’Name’: ’hello’}))
u’Your name is .’
    จากตัวอย่างหากเรา Context ตัวแปรที่ไม่มีอยู่ใน Templates หรือ มีแต่ตัวพิมเล็กใหญ่ไม่ตรงกันนั้นก็จะทำให้ Templates มองว่าตัวแปรที่ Context ไปไม่ใช่ตัว Templates ต้องการซึ่งเดิมๆแล้วนั้นหากตัวแปรที่รอ Context มานั้นหากไม่มีค่าส่งมาให้ Django ก็จะใส่เป็น Empty String ให้เอง

2. เรียนรู้เกี่ยวกับการใช้ Tag

2.1 Tag if else
{% if today_is_weekend %}
<p>Welcome to the weekend!</p>
{% endif %}
    แบบที่ 1 มี Tag if อย่างเดียวหากเข้าเงื่อนไขหรือเป็น True ก็จะนำสิ่งที่อยู่ใน if ใส่เข้าไปในผลลัพธ์จากการ render ด้วย
{% if today_is_weekend %}
<p>Welcome to the weekend!</p>
{% else %}
<p>Get back to work.</p>
{% endif %}
    แบบที่ 2 มี Tag if else ซึ่งก็ใช้หลักการเดียวกับการเขียนโปรแกรมทั่วไปหากไม่เงื่อนไข if ก็จะทำใน else โดยเรายังสามารถใส่ if ซ้อนไว้ใน else ได้อีกด้วยแต่ไม่มีรูปแบบของการเขียน elif

โดยทั้ง 2 แบบนั้นต้องใส่ tag endif เข้าไปด้วยเสมอหากไม่ใส่ก็จะเกิด TemplateSyntaxError.

สิ่งที่น่ารู้เกี่ยวกับ Tag if else ใน Templates ของ Django คือ หากตัวแปรที่เอามาเช็ค if else นั้นมีคุณสมบัติ ตามข้างล่างนี้จะได้ผลเป็น False เสมอ
    - เป็น empty list
    - เป็น empty tuple
    - เป็น empty dictionary
    - เป็น empty string
    - มีค่าเป็น 0
    - เป็น None Object

2.2 Tag for
{% for athlete in athlete_list %}
    <h1>{{ athlete.name }}</h1>
    <ul>
    {% for sport in athlete.sports_played %}
        <li>{{ sport }}</li>
    {% endfor %}
    </ul>
{% endfor %}
    การใช้ for loop ใน Templates ก็สามารถทำได้เช่นกันโดยสามารถใช้วนลูปเข้าถึงตัวแปรทั้งหมดภายใน list ได้สามารถใช้ for ซ้อนไว้ข้างใน for ก็ได้เช่นกัน หรือจะใส่ if else ใน for หรือเอา for ไว้ใน if else ก็สามารถทำได้เช่นกัน
{% for athlete in athlete_list %}
    <p>{{ athlete.name }}</p>
{% empty %}
    <p>There are no athletes. Only computer programmers.</p>
{% endfor %}
    อีกหนึ่งตัวอย่างที่น่าสนใจการมีการเข้าลูป for แต่ตัวที่จะเอามาวนลูปนั้นดันเป็นตัวแปรที่เป็น empty list เราก็สามารถใส่ tag empty ไว้หากเป็น empty list ก็จะใส่ข้อมูลที่อยู่หลัง tag empty ลงไปแทน

นอกจากนี้ for ยังมีสิ่งที่น่ารู้คือ for ใน Templates นั้นจะมีตัวแปรที่สร้างขึ้นตอนที่อยู่ใน for สามารถดึงมาใช้ได้ซึ่งก็คือตัวแปรที่ชื่อ forloop และเมื่อจบลูปตัวแปรนี้ก็จะถูกทำลายทิ้งไป ซึ่งวิธีใช้ก็ต้องใส่ Tag ด้วยดังนี้ {{ forloop }} ซึ่ง forloop นั้นมี attributes ดังนี้
    - forloop.counter จะได้ค่าออกมาเป็นเลขที่บอกจำนวนรอบของ loop ที่กำลังวนอยู่ในขณะนั้น โดยจะเริ่มนับจำนวนรอบที่ 1
    - forloop.counter0 คุณสมบัติเหมือน forloop.counter ทุกประการ แต่สิ่งที่แตกต่างจาก forloop.counter คือจะเริ่มนับจำนวนรอบที่ 0
    - forloop.revcounter จะได้ค่าออกมาเป็นจำนวนของรอบคงเหลือที่ต้องวนลูป ในขณะนั้น โดยจะเริ่มนับจากจำนวนรอบทั้งหมดลดลงไปเรื่อยๆ จนถึง 1
    - forloop.revcounter0 คุณสมบัติเหมือน forloop.revcounter ทุกประการแต่ตอนเริ่มนับจะเริ่มจากจำนวนรอบทั้งหมด - 1 และลดลงเรื่อยๆจนเหลือ 0
    - forloop.first จะได้ผลลัพธ์ออกมาเป็นค่าความจริง True ก็ต่อเมื่อรอบที่วนลูปอยู่นั้นเป็นรอบแรก รอบอื่นๆจะได้ False ทั้งหมด
    - forloop.last จะได้ผลลัพธ์ออกมาเป็นค่าความจริง True ก็ต่อเมื่อรอบที่วนลูปอยู่นั้นเป็นรอบสุดท้าย รอบอื่นๆจะได้ False ทั้งหมด
    - forloop.parentloop จะดึงตัวแปรของ forloop ของลูปชั้นบนออกมาซึ่งมี attributes เหมือนกันทุกประการวิธีเรียก เช่น forloop.parentloop.last เป็นต้น

ตัวอย่างการใช้ forloop
{% for object in objects %}
    {% if forloop.first %}<li class="first">{% else %}<li>{% endif %}
    {{ object }}
    </li>
{% endfor %}
ตัวอย่างการใช้ forloop.parentloop
{% for country in countries %}
    <table>
    {% for city in country.city_list %}
        <tr>
        <td>Country #{{ forloop.parentloop.counter }}</td>
        <td>City #{{ forloop.counter }}</td>
        <td>{{ city }}</td>
        </tr>
    {% endfor %}
    </table>
{% endfor %}
2.3 Tag ifequal ifnotequal (ใช้รูปแบบเดียวกันต่างกันที่เช็คว่าเท่ากันไหม หรือ ไม่เท่ากัน)
{% ifequal user currentuser %}
    <h1>Welcome!</h1>
{% endifequal %}
    แบบที่ 1 ใช้เปรียบเทียบระหว่างตัวแปรกับตัวแปร จากตัวอย่างนี้เป็นการเทียบว่า user = currentuser หรือไม่ ถ้าเท่ากันก็จะใส่ <h1>Welcome!</h1> เข้าไปในผลลัพธ์
{% ifequal section ’sitenews’ %}
    <h1>Site News</h1>
{% else %}
    <h1>No News Here</h1>
{% endifequal %}
    แบบที่ 2 Tag ifequal และ ifnotequal ก็รองรับการใช้ Tag else ได้เช่นกับเดียวกับ Tag if แบบปกติ นอกจากนั้น ifequal และ ifnotequal ยังสามารถใช้เทียบระหว่างตัวแปร กับ ข้อมูลที่ต้องการเช็คตรงๆเลยก็ได้เช่นกันแต่มีข้อจำกัดอยู่ว่ารูปแบบนี้สามารถใช้ตัวแปรเทียบได้แค่ 4 รูปแบบนี้เท่านั้นคือ
    - 1
    - 1.23
    - ’foo’
    - "foo"

 3. หลักจากศึกษาวิธีการใช้และรูปแบบการเขียน Templates กันไปแล้วมาเริ่มทดลองใช้ Templates กันเลยดีกว่า

3.1 สร้างโฟลเดอร์สำหรับการเก็บ Templates ขึ้นมาก่อนจะไว้ที่ไหนก็ได้แต่แนะนำให้ไว้ที่เดียวกับที่มีไฟล์ manage.py เพราะง่ายต่อการเข้าถึงและเห็นชัดเจนเมื่อสร้างแล้วจะได้รูปแบบประมาณนี้


3.2 เมื่อสร้างโฟลเดอร์แล้วเราต้องบอกให้ Django รู้ก่อนว่าโฟลเดอร์นี้นะเราจะใช้เก็บ Templates ทั้งหมดของเราไว้ ดังนั้นให้เข้าไปแก้ไขไฟล์ settings.py ในโฟลเดอร์ mysite โดยเพิ่มข้อความดังนี้
TEMPLATE_DIRS = (
    '/home/django/mysite/templates',
)
เพื่อเป็นการระบุที่อยู่ของ Templates ให้ Django รู้แต่การกำหนดรูปแบบนี้ไม่สมควรใช้เนื่องจากหากมีเปลี่ยนเครื่องก็จะทำให้ Directory ที่ลงไว้ใน settings ไม่ตรงกับเครื่องนั้นแล้วทำให้หาไฟล์ Templates ไม่เจอในที่สุดดังนั้นวิธีแก้เปลี่ยนไปใช้รูปแบบของที่อยู่ดังนี้
TEMPLATE_DIRS = (
    os.path.join(BASE_DIR, 'Templates').replace('\\','/'),
)
 BASE_DIR เป็นตัวแปรที่มีอยู่แล้วใน settings ซึ่งจะดึงที่อยู่ ณ ปัจจุบันมาให้เราใช้ได้เลย

3.3 เข้าไปยังโฟลเดอร์ Templates ที่เราสร้างขึ้นในข้อ 3.1 แล้วสร้างไฟล์ชื่อ current_datetime.html แล้วใส่โค้ดในไฟล์ HTML ดังนี้
<html><body>It is now {{ current_date }}.</body></html>
3.4 เข้าไปแก้ไขไฟล์ views.py ในโฟลเดอร์ mysite โดยเพิ่มโค้ดและแก้ไขดังนี้
from django.template.loader import get_template
from django.template import Context

def current_datetime(request):
    now = datetime.datetime.now()
    t = get_template('current_datetime.html')
    html = t.render(Context({'current_date': now}))
    return HttpResponse(html)
เมื่อแก้ไขเสร็จแล้วลองเข้าไปที่ http://localhost:8000/time/ ดูจะพบว่าหน้าเว็บของเราจะแสดงเวลา ณ ปัจจุบันออกมาเหมือนกับฟังก์ชั่นที่เราเขียนไว้ก่อนหน้าใน Chapter 3


แต่ฟังก์ชั่นที่เราแก้ไขเมื่อสักครู่เราสามารถทำให้สั้นลงได้อีกด้วยการใช้ render_to_response ดังนี้
from django.shortcuts import render_to_response

def current_datetime(request):
    now = datetime.datetime.now()
    return render_to_response('current_datetime.html', {'current_date': now})
ก็จะให้ผลเหมือนกันแต่โค้ดสั้นลงเนื่องจาก Django มี API ที่ชื่อ render_to_response อยู่แล้วซึ่งเรา import มาจาก django.shortcuts แล้วนำมาใช้ได้เลย แต่ก็ยังมีวิธีที่สั้นลงไปอีกโดยการใช้ locals() แทนการเขียนตัวแปรที่ใช้ Context ทั้งหมดดังนี้
def current_datetime(request):
    current_date = datetime.datetime.now()
    return render_to_response('current_datetime.html', locals())
โดยหลักการของ locals() คือการนำ local variable ทั้งหมดที่มีในฟังก์ชั่นนี้ส่งไปให้ Templates ทั้งหมด ดังนั้นการตั้งชื่อตัวแปรจึงสำคัญเพราะตัวแปรที่เราจะแทนค่าใน Templates หากไม่มีชื่อตรงกับใน local variable ก็จะไม่มีตัวแปรไป render และที่สำคัญอีกอย่างคือการส่งตัวแปร local variable ไปทั้งหมดนั่นหมายถึงการส่ง request ไปให้ Templates ด้วยเช่นกันดังนั้นหากจะใช้วิธีลัดแบบ locals() นั้นต้องระมัดระวังเป็นพิเศษและการใช้ locals() นี้มีข้อดีเพียงแค่เขียนสั้นลงเท่านั้น

3.5 สร้างโฟลเดอร์ includes โดยเข้าไปเก็บไว้ในโฟลเดอร์ Templates ที่สร้างในข้อ 3.1 ให้เป็น Sub Directory และสร้าง Templates ชื่อ nav.html มีโค้ดภายในดังนี้
<div id="nav">
You are in: {{ current_section }}
</div>
    จากนั้นเข้าไปแก้ไข Templates current_datetime.html โดยเพิ่ม Tag includes เข้าไปจะได้ดังนี้
<html>
<body>
{% include "includes/nav.html" %}
It is now {{ current_date }}.
</body>
</html>
    เมื่อใส่ Tag includes เข้าไปสังเกตจะเห็นว่า ที่อยู่เป็น includes/nav.html ซึ่งหากใน views ของเรานั้นอยากใช้ Temmplates ที่อยู่ในโฟลเดอร์ includes ก็สามารถพิมที่อยู่ของไฟล์แบบเดียวกับในตัวอย่างนี้ได้เลย และเนื่องจากเราดึง Templates อื่นเข้ามาใช้ใน Templates current_datetime.html ด้วยดังนั้นตัวแปรที่ nav.html ต้องการให้ Context ไปเราก็ต้อง Context ไปให้ด้วยเช่นกันดังนั้นเข้าไปแก้ไขไฟล์ Views โดยเพิ่มโค้ดเข้าไปดังนี้
def current_datetime(request):
    current_date = datetime.datetime.now()
    current_section = "/time/"
    return render_to_response('current_datetime.html', locals())
โดยเบื้องต้นกำหนด current_section ให้เป็น /time/ เพื่อนำไปแสดงผลหากเราไม่ Context current_section ไปหน้าเว็บส่วนที่ต้อง Context ก็จะกลายเป็นช่องว่างๆไป

ตัวอย่างเมื่อ Context current_section ไป


 ตัวอย่างเมื่อไม่ Context current_section ไป


    จาก Chapter 4 นี้ Templates ช่วยให้เราแยกโค้ด Python และ โค้ด HTML ออกจากกันได้อย่างสมบูรณ์พร้อมทั้งสามารถนำ Templates มาใช้ได้เรื่อยๆไม่ต้องเขียนใหม่ซ้ำๆการใช้ includes ทำให้เราสามารถกำหนดรูปแบบของ Header และ Footer ของเว็บโดยที่ไม่จำเป็นต้องนั่งพิมทั้ง Header และ Footer ในทุกๆ Templates ที่เราสร้างการใช้ Tag และ Filters ใน Templates เพื่ออำนวยความสะดวกในการนำ Object มา render แล้วนำไปแสดงผล
Read more ...

Django Book Chapter 3 : Views and URLconfs

    จาก Chapter 2 นั้นเราได้สร้างโปรเจคที่ชื่อ mysite ไว้แล้วดังนั้นจะเริ่ม ต้นเรียนรู้การใช้งาน Views และ Urls เบื้องต้นโดยการสร้างเพจที่แสดงคำว่า Hello world ขึ้น

1.สร้างไฟล์ชื่อ views.py ไว้ในโฟลเดอร์ชื่อ mysite ที่อยู่ภายในของโปรเจค mysite ของเราและเขียนโค้ดภายในไว้ดังนี้
from django.http import HttpResponse
def hello(request):
    return HttpResponse("Hello world")
    ซึ่งโค้ดที่เขียนลงไปนั้นคือการสร้างฟังก์ชั่นที่ชื่อ hello ขึ้นมามี Argument 1 ตัวชื่อ request ซึ่งจะเป็น Objects ที่เก็บข้อมูล Web ที่ส่ง request มายัง Views นี้โดยเมื่อเรียกฟังก์ชั่นนี้จะตอบสนองแบบ http ส่งเป็นข้อความว่า Hello world กลับไปและใน views.py นี้ได้มีการ import API มาจาก Django ชื่อ HttpResponse
    จากนั้นหากลอง runserver แล้วเข้าไปยังหน้าเว็บของเรานั้นก็จะยังไม่พบคำว่า Hello world แต่จะยังคงขึ้น It worked! แบบใน Chapter 2 เนื่องจาก Django ยังไม่รู้ว่าเมื่อใดที่เราจะต้องเรียกฟังก์ชั่น hello นี้ขึ้นมาใช้

ภาพตัวอย่างที่อยู่ของไฟล์ views.py


2.จากในข้อ 1 หากเราต้องการให้ Django รู้ว่าเราต้องจะเรียกใช้ฟังก์ชั่น hello ที่อยู่ใน views เมื่อใดก็ต้องใช้ Urls เป็นตัวกำหนดดังนั้นเปิดไฟล์ urls.py ที่อยู่ที่เดียวกับที่เราสร้าง views.py ไปในข้อ 1 แล้วเพิ่ม from mysite.views import hello เข้าไปและเพิ่ม ('^hello/$', hello), เข้าไปใน urlpatterns จะได้รูปแบบดังนี้


    โดยเราได้ import ฟังก์ชั่น hello ใน views.py เข้ามาเพื่อใช้ใน urlpatterns โดย ('^hello/$', hello), เป็นการบอกว่าหากมีการเรียก urls เป็น http://localhost:8000/hello/ ก็จะให้เรียกฟังก์ชั่น hello เป็นตัวจัดการว่าจะส่งอะไรกลับไปแสดงผล โดย hello ส่วนแรกจะเป็นการระบุรูปแบบของ urls โดยมี regular expressions "^" เป็นตัวบอกว่าเริ่ม และ "$" เป็นตัวบอกว่าจบ ส่วน hello ตัวที่ 2 ใช้บอกว่าหากมีชื่อ urls แบบ hello ตัวแรกนั้นจะเรียกฟังก์ชั่นอะไรมาจัดการซึ่งในตัวอย่างนี้ก็เรียกฟังก์ชั่น hello มาจัดการนั่นเอง ทดลองเข้าไปที่ http://localhost:8000/hello/ ก็จะแสดงผลออกมาเป็น hello world ดังนี้


3.หากเราลองเรียก http://localhost:8000/ จะแสดงหน้า 404 Error เหตุผลเพราะเราไม่ได้ตั้งค่าที่ urlpatterns ใน Urls.py ว่าหากมีการเรียกหน้า http://localhost:8000/ จะให้ฟังก์ชั่นอะไรมาจัดการเมื่อไม่มีฟังก์ชั่นไหนมาจัดการก็เลยทำให้เกิด Error ขึ้นอย่างที่เห็น

ภาพตัวอย่างหน้า 404 Error


4.รูปแบบการจัดการ request ของ Django นั้นเมื่อมี request เข้ามานั้น จะอ่านค่า ในไฟล์ setting.py หัวข้อ ROOT_URLCONF ว่ามีค่าเป็นอะไรในเบื้องต้นโปรเจคที่เราสร้างนั้นจะกำหนดไว้เป็นดังนี้ ROOT_URLCONF = 'mysite.urls' ซึ่งก็คือการกำหนดให้อ่านค่าจากไฟล์ urls.py ที่เราแก้ไขในข้อ 2 นั่นเองจากนั้นก็เข้าไปจัดการตามสิ่งที่เราเขียนไว้ใน views และ urls จะได้ค่ากลับมาเป็น HttpResponse เมื่อได้มา Django ก็ทำการแปลงให้เป็นโค้ด HTML กลับไปแสดงผลที่ Browser นั่นเอง

5.หน้าเว็บนั้นหลักๆมีอยู่ 2 ประเภทนั่นคือรูปแบบ Static และ Dynamic ซึ่งตัวอย่างของ Static นั้นก็คือ Hello world ที่เราทำไปแล้วนั่นเอง โดย Static คือไม่ว่าเราจะเรียกหน้านี้ที่เวลาใดๆ ก็จะยังคงให้ข้อมูลกลับมาเหมือนกันทุกครั้ง แต่หากเป็นแบบ Dynamic ข้อมูลที่ได้จะมีการเปลี่ยนแปลงไปตามเวลาที่เรียกใช้ตามตัวอย่างต่อไปนี้

5.1 แก้ไขไฟล์ views.py โดยเพิ่มโค้ดเข้าไปดังนี้
import datetime
def current_datetime(request):
    now = datetime.datetime.now()
    html = "<html><body>It is now %s.</body></html>" % now
    return HttpResponse(html)
เมื่อเพิ่มเสร็จแล้วจะได้รูปแบบดังนี้


    จากโค้ดจะเป็นการ import API ที่ชื่อ datetime เพิ่มเข้ามาเพื่อใช้ในฟังก์ชั่น current_datetime ซึ่ง ฟังก์ชั่นนี้เมื่อมีการเรียกจะนำค่าวันที่เวลา ณ ตอนที่เรียกนั้นส่งกลับไปใน HttpResponse ให้ Django ไปจัดการต่อเอง

5.2 แก้ไขไฟล์ urls.py โดยเพิ่ม current_datetime เข้าไปในบรรทัดที่ import views เข้ามา และเพิ่ม ('^time/$', current_datetime), เข้าไปใน urlpatterns จะได้ดังรูปนี้


5.3 ทดลองเข้าไปที่ http://localhost:8000/time/ จะแสดงเวลาปัจจุบันให้เราแต่ หากสังเกตดีๆจะพบว่าเวลาที่ได้จะมีความเพี้ยนซึ่งเกิดจาก Time Zone ที่เราอยู่ไม่ตรงกับค่าที่ Django ตั้งมาให้เป็นมาตราฐาน ซึ่งคือ  UTC ดังนั้นวิธีแก้ไขให้เราเปิดไฟล์ settings.py แล้วมองหาหัวข้อ TIME_ZONE จากนั้นแก้ไขเป็น Asia/Bangkok ตามรูป


 ภาพตัวอย่างตอนที่ยังไม่แก้ไข Time Zone


ภาพตัวอย่างหลังจากแก้ไข Time Zone


6.นอกจากหน้าเว็บที่สามารถทำเป็นแบบ Dynamic ได้แล้วนั้น Urls เองก็สามารถทำให้เป็นรูปแบบของ Dynamic ได้ด้วยเช่นกัน หากเราต้องการใช้รูปแบบ Urls ดังนี้
urlpatterns = patterns('',
    ('^time/$', current_datetime),
    ('^time/plus/1/$', one_hour_ahead),
    ('^time/plus/2/$', two_hours_ahead),
    ('^time/plus/3/$', three_hours_ahead),
    ('^time/plus/4/$', four_hours_ahead),
)
เราสามารถแก้ไขให้เป็นรูปแบบดังนี้
urlpatterns = patterns('',
    # ...
    (r'^time/plus/\d+/$', hours_ahead),
    # ...
)
ซึ่ง \d+ เป็นการระบุว่าสามารถใส่เป็นเลขอะไรก็ได้กี่หลักก็ได้ แต่หากเราต้องการกำหนดให้ใส่เลขไม่เกิน 2 หลักก็ให้ใช้ดังนี้ \d{1,2} ซึ่งเป็นอีกหนึ่งใน regular expressions ดังนั้นแก้ไขไฟล์ urls.py ดังนี้


และเพิ่มฟังก์ชั่น hours_ahead ใน views.py ดังนี้
def hours_ahead(request, offset):
    try:
        offset = int(offset)
    except ValueError:
        raise Http404()
    dt = datetime.datetime.now() + datetime.timedelta(hours=offset)
    html = "<html><body>In %s hour(s), it will be %s.</body></html>" % (offset, dt)
    return HttpResponse(html)
    โดยฟังก์ชั่นนี้มี Arguments 2 ตัวคือ request และ offset ซึ่ง offset นั้นจะเอาค่าของเลขที่เราใส่ใน Urls มาใช้ โดยฟังก์ชั่นนี้ใช้ API datetime ในดึงเวลามาแล้วบวกเพิ่มไปด้วย datetime.timedelta ไปเป็นจำนวนชั่วโมงตามค่าของ offset ที่รับมา จะสังเกตได้ว่าช่วงแรกนั้นมีการใช้ try & except ด้วยเนื่องจากค่าที่เราใช้ในการคำนวณเวลาต้องเป็นตัวเลขเท่านั้นหากมีการใส่ค่าใน urls มาเป็นตัวอักษรก็จะแปลงค่าจาก String ที่ได้มาจาก Urls ไปเป็น int ไม่ได้แล้วเกิด ValueError ขึ้นเพื่อป้องกันความผิดพลาดตรงนี้เลยมีการใส่ try & except เข้าไปเพื่อไม่ให้ Error ส่วนนี้สร้างปัญหาให้กับ Web Application ของเราได้ โดยหากเกิด ValueError ก็จะเปลี่ยนเพจจากการแสดงผลตามปกติไปเป็นหน้า 404 Error แทน

ภาพตัวอย่างเมื่อใส่ค่า 12 ลงใน Urls


ภาพตัวอย่างเมื่อใส่ค่า 100 ลงใน Urls จะเกิด Error เนื่องจากรูปแบบของ Urls


ภาพตัวอย่างเมื่อใส่ตัวอักษรลงใน Urls


    จาก Chapter 3 นี้เราสามารถทำให้ทั้ง Urls และ Views ของเรานั้นอยู่ในรูปแบบของ Dynamic ได้ด้วยการใช้ regular expression เป็นตัวช่วยในส่วนของ Urls และ API ของ Python และ Django มาช่วยใน Views อีกทั้งการเขียนฟังก์ชั่นในการแสดงผลควรจะมีการคิดถึงกรณีที่ผู้ใช้ใส่ค่ามามาผิดรูปแบบจากที่ต้องการเช่นใส่ ตัวอักษรมาให้แต่ฟังก์ชั่นเราต้องการตัวเลข ในส่วนนี้เป็นส่วนที่ต้องคำนึงถึงในการพัฒนา Web Application ขึ้นด้วย


Read more ...

วันจันทร์ที่ 20 มกราคม พ.ศ. 2557

Django Book Chapter 2 : Getting Started

    เริ่มต้นนั้น Django ต้องใช้ภาษา Python เป็นตัวหลักในการทำงานดังนั้นต้องลง Python ก่อนโดยสามารถหาไฟล์ที่ใช้ในการลงกับวิธีการลงได้ที่ http://www.python.org/download/ โดยแนะนำให้ลงเวอร์ชั่น 2.X สำหรับคนเริ่มต้นเรียนรู้ภาษา Python โดยผู้เขียนใช้เวอร์ชั่น 2.7.3

    จากนั้นจึงลง Django แนะนำให้ลงเวอร์ชั่นล่าสุด ซึ่งสามารถหาไฟล์กับวิธีการลงได้ที่นี่ https://www.djangoproject.com/download/

    เริ่มสร้าง Project โดย Directory ที่สร้างนั้นจะเป็น root ซึ่งแล้วแต่เราเลยว่าจะสร้างไว้ที่ไหนก็ได้ซึ่งโดยทั่วไปปกติจะวางไว้ที่ /var/www แต่สำหรับ Django นั้นจะมอง root เป็นที่ที่เก็บโฟลเดอร์ของโปรเจคไว้ เหตุผลที่ไม่วางไว้ใน /var/www เพราะบุคคลอื่นจะสามารถดู Code ที่เราเขียนไว้ผ่านทาง Web Browser ได้หากเราวาง Code ไว้ในนั้น เมื่อเลือก Directory ที่จะใช้เก็บโปรเจคได้แล้วให้เปิด Terminal เข้าไปยัง Directory ที่ต้องการจากนั้นพิม django-admin.py startproject mysite จะเป็นการสร้างโปรเจคและมีรูปแบบของโฟลเดอร์ดังนี้
mysite/
    manage.py
    mysite/
        __init__.py
        settings.py
        urls.py
        wsgi.py
    จากนั้นพิมคำสั่ง python manage.py runserver โดย port ที่ใช้เป็นค่าเริ่มต้นจะเป็น 8000 ซึ่งจะรัน server ที่ localhost ของเครื่องเรา แต่หากต้องการเปลี่ยนไป port อื่นก็สามารถทำได้ โดยพิม python manage.py runserver 8080 ตอนจะรัน server ดังนั้น port ก็จะไปใช้ port 8080 และหากต้องการให้เครื่องอื่นที่อยู่ใน Network เดียวกับเราสามารถเข้ามาเปิด Web Application ของเรานั้นต้องพิม python manage.py runserver 0.0.0.0:8080 ตอนจะรัน server โดยเครื่องอื่นให้พิม Urls ใน Browser เป็น ip ของเครื่องที่รัน server อยู่ตามด้วยพอร์ท เช่นเครื่องที่รัน server มี ip เป็น 192.168.1.100 ก็ให้พิมใน Browser ว่า http://192.168.1.100:8000/ เป็นต้น

ภาพตัวอย่างจาก Terminal


    จากนั้นลองเปิดเข้าไปใน Browser ของแล้วพิม http://127.0.0.1:8000 จะแสดงหน้าเว็บดังรูปนี้ ซึ่ง 127.0.0.1 คือ ip ของ localhost นั่นเอง โดยนอกจากการพิม http://127.0.0.1:8000 แล้วนั้นเรายังสามารถพิมว่า http://localhost:8000/ ก็ได้ผลแบบเดียวเช่นกัน


Read more ...

Django Book Chapter 1 : Introduction to Django

    Django คือ Web Framework ซึ่งใช้ในการช่วยพัฒนา Web Application ให้ง่ายขึ้นลดความซับซ้อนและความยุ่งยากและเวลาที่ใช้ในการพัฒนา Web Application ลงไปอย่างมาก

    จากตัวอย่างการพัฒนา Web Application โดยไม่ใช่ Web Framework มาช่วยที่มีใน Django Book นั้นจะเห็นได้ว่ามีความยุ่งยากและซับซ้อนกว่ามาก อีกทั้งยังต้องคอยจัดการ Database Connection เองอีกด้วยซึ่งรูปแบบที่ใช้กันจะเป็นไฟล์นามสกุล .cgi

    โดยรูปแบบของการสร้าง Web Application โดยใช้ Django นั้นมีส่วนประกอบหลักๆ 4 ส่วนคือ Models , Views , Urls และ Templates ซึ่งทั้ง 4 ส่วนนี้เขียนขึ้นมาด้วยภาษา Python

    - Models นั้นเป็นการเขียนรูปแบบของ Database ที่เราต้องการสร้างขึ้นด้วยภาษา Python

    - Views จะเป็นการเขียนฟังก์ชั่นเพื่อเอาไว้เรียกใช้เมื่อมีการเรียก Urls และ Urls จะมาเรียกฟังก์ชั่นใน Views ที่เราไว้เขียนออกไปแสดงผล

    - Urls เป็นส่วนที่ใช้จัดการชื่อ Urls เวลาที่ผู้ใช้พิม Urls มาจะนำมาเทียบกับรูปแบบที่มีใน Urls หากตรงกันก็จะไปเรียกฟังก์ชั่นใน Views ที่เราเขียนไว้

    - Template เป็นแบบฟอร์มของหน้าเว็บ HTML ที่เราสร้างไว้เพื่อนำมาข้อมูลที่ใช้ในการแสดงผลมาใส่เข้าไปแล้วส่งกลับไปแสดงผลให้ผู้ใช้
Read more ...

วันพฤหัสบดีที่ 9 มกราคม พ.ศ. 2557

Work 1 Resource Tracking - Last Update

Resource Tracking - Account Statement

1.แก้ไขชื่อฟังก์ชั่นใน templatetags filters ให้สื่อความหมายมากขึ้นกว่าเดิม

2.เขียนไฟล์ test.py ซึ่งมีทั้งหมด 19 tests เป็นการเช็คการแสดงผลของ Web Application ถูกแสดงผลออกมาได้ถูกต้องหรือไม่


ภาพตัวอย่างเมื่อรัน tests.py ผ่านครบทั้ง 19 กรณี


Read more ...

วันพุธที่ 8 มกราคม พ.ศ. 2557

Work 1 Resource Tracking - Update 3

Resource Tracking - Account Statement

1.แก้ไขไฟล์ Readme.txt ที่สร้างไว้ตอนแรกเปลี่ยนไปใช้เป็น Readme.rst ซึ่งเป็น format แบบ reStructuredText ซึ่งเมื่อ Upload Repositories แล้วจะแสดงข้อความในไฟล์ Readme.rst พร้อมจัดรูปแบบการแสดงผลตามที่เขียนไว้ในไฟล์ ซึ่งตอนที่ใช้ Readme.txt ก็จะแสดงเหมือนกันแต่จะไม่มีการจัดรูปแบบการแสดงผลซึ่งจะทำให้อ่านยากหาก Readme ของเรานั้นมีข้อมูลเยอะๆ

2.เพิ่ม templatestags filters เข้ามาเพื่อใช้ใน Templates สำหรับแสดงหน้า View Asset ที่มี filters ในรูปแบบต่างๆเช่น แสดงเฉพาะวันที่ , เดือน , ปี เป็นต้น โดยใน Templatetags นั้นได้ import API date , timedelta จาก datetime และ timezone จาก django.utils

ภาพตัวอย่างหน้า View Asset ที่เพิ่ม templatetags filters


 ภาพตัวอย่างหลังจาก commit Readme.rst ไปยังเว็บ http://bitbucket.org/


Read more ...

วันจันทร์ที่ 6 มกราคม พ.ศ. 2557

Work 1 Resource Tracking - Update 2

Resource Tracking - Account Statement

1.เพิ่มหัวข้อ Description เข้าไปใน Models แล้วเพิ่มช่องสำหรับรับค่า Description ในหน้า Add Income และ Add Expenses เพิ่มการแสดงผลของ Description ใน View Asset
2.เขียน Test สำหรับหน้าที่ใช้ในการแสดงผลทุกหน้า ที่มี ณ ปัจจุบัน

3.สร้างหน้าสำหรับการสร้าง Profile ขึ้นมาชื่อ Create Account

4.สร้างหน้าสำหรับการลบ Profile ออกชื่อ Delete Account

5.จากเดิมในหน้า Menu จะมีเมนู Edit income & expenses ทำการเปลี่ยนเมนูนี้ออก แล้วใส่ Delete Account เข้าไปแทน

6.ในหน้า Index ของ App Account_Statement เพิ่มเมนู Create Account เข้าไป

7.ปรับปรุง Templates ในการแสดงผลเพื่อให้ดูเป็นระเบียบและเรียบร้อยมากขึ้น

ภาพตัวอย่างหน้า Add Income และ Add Expenses ที่ปรับปรุงใหม่



ภาพตัวอย่างหน้า View Asset ที่ปรับปรุงใหม่


ภาพตัวอย่างหน้า Delete Account ที่สร้างขึ้นมาใหม่


ภาพตัวอย่างหน้า Create Account ที่สร้างขึ้นมาใหม่


ภาพหน้า Menu ที่แก้ไขล่าสุด


Read more ...

วันอาทิตย์ที่ 5 มกราคม พ.ศ. 2557

Work 1 Resource Tracking - Problem OperationalError with Solution

Problem OperationalError with Solution

    หลังจากที่เราทำการแก้ไข Models นั้นหลายๆคนคงต้องเจอปัญหา OperationalError พร้อมกับบอกว่า ไม่มี Field XXX ใน Table กันบ้างมาไม่มากก็น้อยโดยปัญหานี้เกิดจากเวลาที่เราให้ตัว Django syncdb แต่ตัว syncdb นั้นไม่ยอมแก้ไข table ให้ทำให้เกิดปัญหาดังกล่างขึ้น ซึ่งวิธีที่ผมเคยใช้แก้ปัญหานั้นคือการลบ db.sqlite3 แล้วสร้างขึ้นใหม่แต่นั่นทำให้ Data ทั้งหมดในนั้นต้องหายไปด้วย ดังนั้นวันนี้ผมจึงขอเสนอวิธีการแก้ไขปัญหาโดยที่ Data ของเรายังอยู่ครบเหมือนเดิมกันครับ

1.ดาวโหลด SQLite database browser ซึ่งเป็นโปรแกรมแบบ Open source หาโหลดได้จาก Ubuntu Software Center ที่มีมากับ OS Ubuntu ได้เลยครับ


โดยโปรแกรมที่เราโหลดตัวนี้สามารถเปิด db.sqlite3 ของเรามาทำการแก้ไขแบบ Manual ได้เลย

2.เปิด Terminal จากนั้น cd ไปยัง Directory โปรเจค Django ของตนเองจากนั้นพิม
python manage.py sql "Appname"
 โดย "Appname" นั้นเป็นชื่อ App ที่แต่ละคนตั้งเองครับจะได้ดังตัวอย่างนี้


ให้เปิด Terminal หน้านี้ทิ้งไว้ก่อนจะนำไปใช้ในลำดับถัดไป

3.เปิดโปรแกรม SQLite database browser ที่เราโหลดมา จากนั้นเปิดไฟล์ db.sqlite3 ของเราที่มีปัญหาอยู่


 4.จากนั้นกดปุ่มรูปตารางที่มีดินสอตามรูปด้านล่างนี้


5.จากนั้นจะมีหน้าต่างขึ้นมาให้เลือก table ที่เราต้องการแก้ไขให้เลือกอันที่เราแก้ไขใน Models ไปหลังสุด


6.จะปรากฎหน้าต่างรูปแบบนี้ขึ้นมาโดยในส่วนของ Field name และ Field type จะแตกต่างกัน จาากจุดนี้ให้ย้อนกลับไปดูที่ Terminal ในข้อ 2 ที่ให้เปิดไว้ ว่ามีอะไรที่ใน SQLite database browser นั้นไม่มีแต่ใน Terminal มี โดยใน Terminal จะเป็น Field name เว้นวรรคแล้วตามด้วย Field type โดยชื่อของ table จะอยู่ด้านบนระบุไว้เรียบร้อยแล้ว


7.จากข้อ 6 ในตัวอย่างนี้นั้นตัว Description เป็นตัวที่ไม่มีก็ให้เรากดปุ่ม Add field จากนั้น กรอก Field name เป็นชื่อของตัวที่ขาดหายไปจาก table


8.ให้เลือกเลือก Field type ใส่ซึ่งถ้าไม่มีแบบที่ตรงกับ Terminal ก็ให้กดปุ่ม ... ด้านข้างแล้วพิมเอง


9.กด OK และ Create

10.ทำซ้ำข้อ 4-9 จนใน db.sqlite3 ของเรามี table ตรงกับใน terminal ทั้งหมดก็ให้กด save แล้วปิดโปรแกรมลองรัน Django แล้วทดสอบ Web Application ของเราอีกครั้ง
Read more ...

Work 1 Resource Tracking - Update 1

Resource Tracking - Account Statement

1.ทำหน้า Add Income และ Add Expenses โดยใช้ Form ใน Templates รับค่าจากหน้า Web Browser ไปจัดการต่อใน Python Code Views โดยมีการเช็คเงื่อนไขไว้หากค่าที่รับมานั้นติดลบ หรือไม่ใช่ตัวเลขจะเด้งกลับหน้า Add Income หรือ Add Expenses ที่ส่งค่ามาให้ก่อนหน้านี้เพื่อให้ใส่ค่าใหม่อีกครั้ง

2.ทำการเปลี่ยนรูปแบบ Field ของ Asset และ amount ใน Class Profile และ income_expenses จาก IntegerField ไปเป็น FloatField เพื่อให้รองรับค่าตัวเลขแบบจุดทศนิยมได้

3.สร้างหน้า View Asset ขึ้นโดยเป็นหน้าที่แสดงรายการทั้งหมดของบัญชีที่ใส่ค่าไว้ในรูปแบบของตารางพร้อมทั้งแสดงเงินคงเหลือจากรายรับและรายจ่ายทั้งหมดที่หักลบกันแล้ว

4.สร้าง Link กลับไปยังหน้าหลักให้ Template ทั้งหมด และ สำหรับ View Asset จะมี Link ไปยังหน้า Add Income และ Add Expenses ให้เป็นพิเศษด้วย

5.ปรับปรุง Templates ทั้งหมดให้เป็น HTML Code เต็มรูปแบบ ปรับการแสดงผลสำหรับทศนิยมเป็น 2 ตำแหน่งและใส่ Comma เมื่อเลขเกินหลักร้อยอัตโนมัติ นอกจากนี้ยังใช้ Link แบบ Dynamic ด้วย namespace จาก Urls ทั้งหมด

6.แก้ไข Models อีกครั้งโดยเพิ่มตัวข้อที่ชื่อ Accountname ใน Profile และ Description ใน income_expenses เป็น CharField ที่กำหนดความยาวสูงสุดไว้ที่ 200 ตัวอักษร

7.สร้างหน้า Index Page แรกสุด ตอนที่พิม http://127.0.0.1:8000/ โดยมีลิ้งค์เพื่อเข้าไปยัง App Account_Statement และ Admin

ภาพตัวอย่างหน้า Index http://127.0.0.1:8000/


ภาพตัวอย่างหน้า Add Income และ Add Expenses



ภาพตัวอย่างหน้า Add Income เมื่อใส่ตัวอักษรหรือเลขติดลบในช่อง Input


ภาพตัวอย่างหน้า View Asset


Read more ...