You are hereBlogs > jittat's blog > มาสร้าง app สำหรับอัพโหลดรูปกัน (1)
มาสร้าง app สำหรับอัพโหลดรูปกัน (1)
เพื่อหัด Django เราจะมาสร้างโปรแกรมสำหรับ upload รูปกันครับ
ในตอนแรกนี้เราจะสร้างโมเดลและเรียกใช้หน้า admin ของ django มาทดลอง upload กันดูก่อน แล้วในตอนถัด ๆ ไป เราจะเขียนหน้าเว็บของเราเพื่อแสดงรูปและมีฟอร์มให้ upload รูป (และในอนาคตเราอาจเพิ่มให้มี user และให้มีการ follow รูปกันได้)
เนื่องจาก django รองรับการ upload ค่อนข้างดี เราก็จะเขียนได้ค่อนข้างง่ายครับ (อาจจะต้องมีการจัดการเกี่ยวกับ "media" บ้าง แต่ไม่ยากครับ จะยุ่งมากเฉพาะตอนแรกนี้ตอนเดียว)
เกริ่นมาพอแล้ว หาที่เหมาะ ๆ แล้วก็สร้างโปรเจ็ค youpics กันเลยครับ
เสร็จแล้วเราไปแก้ settings.py ในไดเร็กทอรี youpics กันครับ เราจะแก้ไฟล์นี้กันหลายรอบครับ ก่อนอื่น ไปกำหนดค่าให้กับส่วนของ database กันก่อน เราจะใช้ sqlite นะครับ เพราะว่ามันมากับ Python 2.5 อย่างไรก็ตามถ้าไม่มีก็อย่าลืมไปติดตั้งไว้นะครับ
แก้ส่วนของ database สองบรรทัดด้านล่างครับ
DATABASE_NAME = 'db/youpics.db' # Or path to database file...
เราระบุ sqlite3 และเราจะเก็บไฟล์ database ของผมที่ db/youpics.db
อีกจุดใน settings.py ที่เราจะเข้าไปดู แต่ยังไม่ได้แก้ตอนนี้ คือส่วน INSTALLED_APPS อยู่ด้านล่างเลยครับ
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
)
สังเกตว่าจะมีแต่ app ที่มากับ django เดี๋ยวพอเราเริ่มสร้างอะไรแล้ว เราจะมาเพิ่มตรงนี้ แต่ละ app จะมีส่วน model, view และ template เป็นของตัวเอง ในกลุ่มของ app ที่ใส่มาให้ตอนต้นทั้งสี่อันนี้ก็เช่นเดียวกัน ดังนั้นเราจะไปสั่งให้ django ปรับปรุง database ของเราให้มีตารางข้อมูลสำหรับ app พวกนี้ก่อน (เพื่อจะได้ทดสอบด้วยว่าเราตั้งค่าส่วน database เรียบร้อยหรือไม่ครับ)
ก่อนอื่นไปสร้างไดเร็กทอรี db ในไดเร็กทอรีของ project เราก่อนจะได้มีที่เก็บ database
จากนั้นสั่ง
ระบบจะสร้างตารางมากมาย แล้วสักพักถามว่าเราจะสร้าง superuser ด้วยหรือไม่ ให้ตอบตกลงไป และป้อนข้อมูลของเราเองรวมทั้ง password (ที่จำได้) ลงไป เดี๋ยวเราจะใช้อีกตอนทดลองหน้า admin ครับ
ถ้าสร้างได้เรียบร้อยไม่มีปัญหาอะไรแสดงว่าเราตั้งค่า database ใช้ได้แล้ว เรามาเริ่มทำอะไรเป็นเรื่องเป็นราวกันดีกว่าครับ
ใน django แต่ละส่วนย่อยของ project จะเรียกว่า application เราจะสร้าง application ชื่อ pictures ของเราขึ้นมา โดยเรียก
ในไดเร็กทอรี pictures ที่ถูกสร้างขึ้นจากคำสั่งดังกล่าว จะมีไฟล์ __init.py__, models.py และ views.py สร้างขึ้นให้โดยอัตโนมัติ
เราจะไปแก้ไฟล์ pictures/models.py เพื่อระบุโมเดลของเราที่จะใช้เก็บรูป โดยระบุดังด้านล่างครับ
# Create your models here.
class Picture(models.Model):
title = models.CharField(max_length=100)
description = models.TextField()
image = models.ImageField(upload_to="pictures")
สังเกตว่าเราประกาศคลาส Picture ซึ่งสืบทอดมาจากคลาส models.Model จากนั้นเราประกาศฟิลด์ในโมเดลนี้ตามมา โดยในตัวอย่างเราใส่ฟิลด์ไป 3 ฟิล์ด มี title เป็นสตริง, description เป็นเท็กซ์ (สตริงยาวๆ) และ image เป็น ImageField
ฟิลด์ประเภท ImageField จะอำนวยความสะดวกให้เราในการ upload รูปครับ โดยเมื่อผู้ใช้ใส่ไฟล์รูปเข้ามาทางฟอร์ม ไฟล์ดังกล่าวจะถูกคัดลอกไปที่ไดเร็กทอรีที่เราระบุโดยอัตโนมัติ ซึ่งในที่นี้ผมกำหนดให้ไปที่ pictures ซึ่งไดเร็กทอรีดังกล่าวจะอยู่ในไดเร็กทอรีที่เรากำหนดด้วย option MEDIA_ROOT อีกที (เดี๋ยวเราจะไปกำหนดค่านี้ใน settings.py ครับ)
(อย่างไรก็ตามในการจะใช้ ImageField ได้ ระบบของเราจะต้องติดตั้ง Python Imaging Library ด้วย)
พอระบุโมเดลใน application เสร็จแล้ว เราไปแก้ไฟล์ settings.py ให้รวม app pictures ของเราเข้าไป พร้อม ๆ กับตั้งค่าไดเร็กทอรีที่เราจะเก็บไฟล์ที่ upload มาครับ
ก่อนอื่นไปเพิ่ม application กันโดยเพิ่มเข้าไปในรายการ INSTALLED_APPS ครับ ในขณะเดียวกันนี้เราฉวยโอกาสเพิ่ม application admin เข้าไปด้วยครับ เพราะเดี๋ยวจะทดลองความสามารถนี้อันเป็นที่เลื่องลือของ django
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.admin', # เพิ่มสองบรรทัดนี้
'youpics.pictures', # เพิ่มสองบรรทัดนี้
)
จากนั้นไปดูตรงต้น ๆ ไฟล์ครับจะมี option อยู่สองอันที่เกี่ยวข้องกับการ upload ที่เราต้องปรับแต่ง คือ MEDIA_ROOT กับ MEDIA_URL ส่วน MEDIA_ROOT เป็น absolute path ในเครื่องของเราไปยังไดเร็กทอรีที่เก็บไฟล์ ส่วน MEDIA_URL เอาไว้ระบุ url ที่ใช้เข้าถึงของเหล่านั้นครับ ส่วน MEDIA_URL นี่ต้องระวังไม่ให้ซ้ำกับ
ADMIN_MEDIA_PREFIX นะครับ เดี๋ยวจะปนกันเละ
MEDIA_ROOT = '/ใส่พาธเต็มไปยังโปรเจ็ค/youpics/media'
# URL that handles the media served from MEDIA_ROOT. Make sure to..
MEDIA_URL = '/site_media/' # อย่าลืม '/' ปิดท้าย
พอแก้ settings.py เสร็จ เราก็ไปจัดการกับฐานข้อมูลและไดเร็กทอรีอีกหน่อยครับ
อย่างแรก, ทุกครั้งที่เราเพิ่ม application เราจะต้องสั่ง syncdb เพื่อให้ django สร้างตารางและปรับปรุง database โดยสั่ง
ถ้าดูสิ่งที่ syncdb พิมพ์มาจะเห็นว่ามีการสร้างตารางชื่อ pictures_picture มาด้วย อันนั้นของตารางสำหรับโมเดลของเราครับ
แล้วก็ไปสร้างไดเร็กทอรีสำหรับมีเดียครับ (และเอาไว้เก็บไฟล์ด้วย)
mkdir media/pictures
เกือบได้เห็นหน้า admin แล้วครับ ไปแก้ไฟล์ urls.py อีกนิดครับ ข้อมูลการทำ routing หรือการตั้งค่าว่ามีการเรียกเข้ามาที่ url ใดให้ไปเรียกฟังก์ชันใดจะอยู่ในไฟล์นี้ครับ เราต้องไปเพิ่มอะไรนิดหน่อยเพื่อเปิดให้ request มัน route ไปหาส่วน admin ได้ครับ
ไม่ต้องแก้อะไรมาก uncomment บรรทัดที่เขียนไว้ว่าให้ uncomment ถ้าต้องการใช้ admin ครับ
# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
# ...
# Uncomment the next line to enable the admin:
(r'^admin/(.*)', admin.site.root),
)
จะรอช้าอยู่ไย เราเรียก server สำหรับพัฒนาของ django มาเล่นกันเลยครับ
เรียกเสร็จก็ทิ้งตัว server ไว้อย่างนั้นนะครับ เราอาจจะต้อง restart บ้างเป็นครั้งคราว แต่โดยมากเวลาเราแก้โปรแกรมแล้ว server จะ reload ให้เองครับ
เมื่อเรียกเสร็จ ก็เข้าไปดูหน้าเว็บทางบราวเซอร์ได้ที่ http://127.0.0.1:8000/ (หรือ http://localhost:8000/ ตามสะดวก)
เข้าปุ๊บจะเจอ error เลย! โดยมีข้อความบอกว่า url ว่าง ๆ ที่ให้มามันไปหาใครไม่ได้เลย และที่กำหนดไว้ก็มีแต่ ^admin/(.*) เท่านั้น
ไม่เป็นไรครับ ไว้ครั้งหน้าเราค่อยมาเขียนกัน เดี๋ยวเราเข้าหน้า admin เลยดีกว่า ไปที่ url http://127.0.0.1:8000/admin เลยครับ จากนั้นก็ป้อน username กับ password ของ superuser ที่เราป้อนไปในตอนต้นครับ จะได้หน้าตาดังด้านล่างครับ
|
แต่ตอนนี้เราก็ยังทำอะไรไม่ได้ครับ เราต้องไป register กับ admin ให้รู้จักกับโมเดลของเราเสียก่อนครับ
ไปเพิ่มไฟล์ชื่อ admin.py ในไดเร็กทอรีของ app เราครับ (ในไดเร็กทอรี pictures, ที่เดียวกับ models.py ครับ)
from django.contrib import admin
admin.site.register(Picture)
สังเกตบรรทัดแรกนะครับ ว่าคลาส Picture เราอยู่ในโมดูล youpics.pictures.models ครับ
เพิ่มเสร็จแล้ว ก็ไป restart ตัว web server ก่อน โดยการปิดแล้วก็เรียกใหม่ ที่ต้อง restartเพราะว่าการเพิ่มไฟล์จะไม่ทำให้ server มัน reload โปรแกรม จากนั้นทดลองเข้าหน้า admin อีกทีครับ
จะเห็นว่ามีเมนูของ Pictures ปรากฏขึ้นแล้วนะครับ ลองเข้าไปทดลอง add รูปดูนะครับ (ถ้า add แล้วลองเข้าไปดูไดเร็กทอรี media/pictures นะครับ จะเห็นว่ามีไฟล์ปรากฏขึ้นในนั้น ลอง add สักรูปสองรูปนะครับ
ทีนี้หลังจากเล่นดูแล้ว เหลือปัญหาที่เราต้องจัดการอีกสองอย่างนะครับ
อย่างแรกเวลาเพิ่มข้อมูลเข้าไป เวลาแสดงผลของรายการวัตถุในคลาส Pictures (เช่นตอนที่เข้า url
http://127.0.0.1:8000/admin/pictures/picture/) เราจะเห็นว่าในหน้า admin จะแสดงวัตถุแต่ละวัตถุเป็นPicture objectเหมือนกันหมดอย่างที่สองก็คือพอกดไปดูรูปแล้วจะพบ error ว่า Page Not Found
เราจะกำหนดให้เวลาแสดง Picture object นั้นแสดงด้วย title นะครับ เราทำโดยเพิ่มเมท็อด __unicode__ เข้าไปให้คืนค่า title ออกมา เมท็อดนี้จะถูกเรียกโดยอัตโนมัติเมื่อมีการแสดงวัตถุในคลาสดังกล่าวในรูปของสตริงครับ ปรับคลาสของเราเป็นดังนี้ครับ
# ...ละส่วนประกาศฟิลด์เอาไว้...
def __unicode__(self):
return self.title
ทีนี้ลอง refresh หน้าที่แสดงรายการ จะเห็นว่าแสดงด้วย title แล้ว
ขั้นสุดท้าย เราจะจัดการให้การเรียกดูรูปทำได้นะครับ สังเกตว่า url ที่เราเรียกดูรูปคือ http://127.0.0.1:8000/site_media/pictures/cap1.png ปกติแล้วพวกแฟ้ม static ทั้งหลายเรามักจะ host ไว้ที่อื่น โดย django ให้เราระบุ url ได้ตอนที่เรากำหนดค่า MEDIA_URL
แต่ในกรณีนี้เราใช้ server ของ django เพื่อให้บริการไฟล์เหล่านี้ด้วย ทำให้เราต้องไประบุใน url routing (ในไฟล์ urls.py) ด้วยครับ เข้าไปเพิ่มบรรทัดดังกล่าวใน urlpatterns นะครับ อย่าลืมแก้ path ด้วยนะครับ
'django.views.static.serve',
{ 'document_root': '/พาธเต็มไปยังโปรเจ็ค/youpics/media' }),
ทีนี้ เราก็ upload รูป และดูรูปได้แล้ว
คราวนี้เรามัวแต่กำหนดโน่น กำหนดนี่ ที่อาจจะดูเหมือนยุ่งสักหน่อยครับ แต่พอทำพวกนี้เสร็จแล้ว หลาย ๆ อย่างจะง่ายขึ้นครับ พอทำสักครั้งแล้วอะไรก็จะสะดวกแล้วครับ
ใน django ที่หน้า admin ทำมาสวยหรูแบบนี้ เพื่อความสะดวกในการจัดการเว็บที่เราทำ เช่นการเพิ่มข้อมูลอะไรพวกนี้ ทำให้เราไม่ต้องเสียเวลามาทำงานที่ทุก ๆ เว็บไซต์ต้องทำกันอยู่แล้ว
อย่างไรก็ตาม เรายังไม่ค่อยได้เขียนอะไรกันเลย เดี๋ยวคราวหน้าเรามาทำหน้าเว็บของเราเอง ให้แสดงรูปที่ upload มาครับ
- jittat's blog
- Login or register to post comments

ผมลองทดสอบบน django 1.0@Windows
ติดปัญหาตรง admin.autodiscover()
เป็นปัญหาที่ platform หรือปล่าวครับ
ผมลองแล้วเล่นได้นะครับ
นึกไม่ออกเหมือนกันว่าจะพลาดตรงไหนนะครับ
ลองดูว่าได้เอาคอมเม้นต์บรรทัดก่อนหน้า ที่เป็น from django.contrib import admin ออกด้วยหรือเปล่านะครับ
แล้วก็อาจจะลองทดสอบตรง path ใน settings.py ดูนะครับ ต้องใส่เป็นเครื่องหมาย / หมดนะครับ แม้ว่าจะเป็น windows (ไม่ใช้ \ เหมือนใน windows)
แล้วก็สุดท้าย รบกวนลองดูอีกทีว่าเป็นรุ่น django 1.0 หรือเปล่านะครับ ถ้าเป็นรุ่นก่อนหน้า มันจะมีแก้ตรงแถว ๆ นี้ล่ะครับ
ถ้าไม่ได้รบกวนแจ้งรายละเอียดเพิ่มหน่อยนะครับ ว่า Error ว่าอย่างไรครับ
ขอบคุณครับ
เดี๋ยวขอผมไปลองก่อนครับ แล้วจะมาตอบครับ
น่าลองเขียนตามดูบ้างจริงๆ ครับ.
-จงระวัง หากคุณไม่รู้ว่าจะไปทางไหน คุณอาจไปไม่ถึงที่นั้นเลย