สนุกกับ Active Record ภาค Grails : ค้น, ค้น, ค้น

Posted September 11, 2008 at Grails66
จาก entry ที่ rails66 สนุกกับ Active Record: ค้น, ค้น, ค้น มาดู version ของ Grails บ้างครับว่าเป็นอย่างไร เทียบกันแบบ 1 ต่อ 1 ไปเลย เพื่อความมันส์ ขออ้างอิงจาก entry ของคุณ cblue ที่ สนุกกับ ActiveRecord ภาคเกรลส์ class Writer { String firstname String lastname } สร้างข้อมูลกันก่อนครับ import Writer def writer1 = new Writer( firstname:"John", lastname:"Bestman") writer1.save() def writer2 = new Writer( firstname:"Mary", lastname:"Happy") writer2.save() มันไม่สวยเท่าไรที่สร้างนักเขียนแบบนี้ แหม… อายจังครับ [ต้องพูดแบบบุญชูนะครับ] แต่ยังหน้าด้านหน้าทนต่อไปครับ เอาไว้จะปรับปรุงครับ [...]

สกัดบทสนทนาจาก Twitter ด้วย Groovy

Posted September 10, 2008 at Grails66
ตัวนี้เป็น Groovy shell script เพื่อใช้สร้าง twitter log ที่โพสต์ไว้ในเอนทรีก่อนหน้านี้ครับ ตอนแรกว่าจะใช้โค้ดของ @sugree แต่มันใช้อ่าน timeline ที่เป็น private ไม่ได้ ผมเลยต้องเขียนเอง อีกหนึ่งแต่ แต่ด้วยความขี้เกียจส่วนบุคคลเลยไปค้นว่ามี library .jar ไหนบ้างที่พอจะใช้ได้ ก็ไปเจอ Twitter4J เข้าก็เลยไม่ต้องเขียนเองทั้งหมดครับ ประกอบ ๆ กันหน่อยก็เป็นอันเรียบร้อย #!/usr/bin/env groovy import twitter4j.* def cli = new CliBuilder(usage: 'twlog -h for help information') cli.h(longOpt:'help', 'usage information') cli.n(argName:'pages', longOpt:'pages', args:1, required:false, type:Integer, 'pages') cli.u(argName:'user', longOpt:'user', args:1, required:true, type:GString, 'user') cli.p(argName:'password', longOpt:'passwd', args:1, required:true, type:GString, 'password') cli.w(argName:'with', longOpt:'with', [...]

มาดูการจัดการ GORM Relationship แบบ 1 ต่อ 1

Posted September 10, 2008 at Grails66
ตอนนี้เริ่มพูดถึง GORM [ Grails Object Relational Mapping ] กันแล้ว เรื่องที่ขาดไม่ได้คือ การจัดการความสัมพันธ์หรือ Relationship โดยแบ่งออกเป็น 3 แบบคือ 1. one-to-one 2. one-to-many 3. many-to-many ใน entry นี้มาเริ่มดูกันที่ความสัมพันธ์แบบ one-to-one กันก่อนครับ กำหนดให้ Domain class = User เก็บข้อมูลผู้ใช้งาน Domain class = Address เก็บข้อมูลที่อยู่ของผู้ใช้งาน Business Rule : กำหนดให้ผู้ใช้งาน 1 คนมีที่อยู่ที่เดียวเท่านั้น ดังนั้นทำการสร้าง domain class ดังนี้ $grails create-domain-class User $grails create-domain-class Address และทำการแก้ไขดังนี้ /domain/User.groovy class User { String username; String password; } /domain/Address.groovy class Address { String [...]

สนุกกับ ActiveRecord ภาคเกรลส์

Posted September 10, 2008 at Grails66
ไปอ่าน สนุกกับ ActiveRecord เบื้องต้น ของ อ. มะนาว (@jittat) ที่ rails66 มาครับ เลยนึกขึ้นได้ว่าน่าจะกลับมาเขียน content แบบเริ่มต้นบ้าง เพื่อให้เป็นไปในลักษณะเดียวกัน ผมขออนุญาตเอาเอนทรีของ @jittat มาแปลงจาก Rails เป็น เกรลส์ จะได้เปรียบเทียบ feature กันแบบ 1:1 ได้ ActiveRecord pattern ในเกรลส์อย่างที่พูดไว้ใน Quickpod ตอนที่ 5 ครับว่าเกรลส์ใช้ความสามารถของภาษา Groovy เพื่อทำให้มัน dynamic ในหลาย ๆ จุด ก่อนอื่นก็สร้าง application กันก่อนด้วย $ grails create-app bookstore $ cd bookstore แล้วก็เริ่มสร้าง domain class ในเกรลส์ (ใน Rails เรียก model ครับ) $ grails create-domain-class writer ก็จะได้ไฟล์ [...]

มาดูการจัดการ GORM Relationship แบบ One-to-Many

Posted September 15, 2008 at Grails66
ต่อจากจาก entry นี้ครับ มาดูการจัดการ GORM Relationship แบบ 1 ต่อ 1 มาดูต่อไปว่าจะจัดการความสัมพันธ์แบบ one-to-many ได้อย่างไร โดยผมจะใช้ตัวอย่างจาก สนุกกับ Active Record ภาค Grails : ค้น, ค้น, ค้น มาเริ่มกันเลยครับ … go go go !!!! กำหนดให้ Domain class 2 ตัวคือ - Writer เก็บข้อมูลของนักเขียน - Book เก้บข้อมูลของหนังสือ Business Rule - หนังสือ 1 เล่มสามารถมีผู้แต่งได้เพียง 1 คน - นักเขียนสามารถเขียนหนังสือได้มากว่า 1 เล่ม ถ้ายังไม่ทำการสร้าง domain class ให้สร้างดังนี้ $grails create-domain-class Writer $grails create-domain-class Book และทำการแก้ไขดังนี้ /domains/Writer.groovy class Writer [...]

Comet กับ ZKGrails ใน 30 บรรทัด

Posted September 15, 2008 at Grails66
เมื่อคืนคุยกับคุณ up1 ใน twitter เรื่อง Comet ก็เลยได้ฤกษ์ลอง feature ใหม่ใน ZK 3.5 เรื่องของเรื่องคือผมเล็งจะทำไว้ตั้งนานแล้วตั้งแต่คิดจะเขียน vvtalk โปรแกรม audio presentation ใหม่ (จากเดิมใช้ OpenLaszlo แล้วคนบน OS X พิมพ์ไทยไม่ได้เพราะเป็น Flash เลยคิดจะ port มาเป็น ZK) หลายคนอาจจะยังไม่รู้จัก Comet ผมยกตัวอย่างเป็น application ก็แล้วกันครับ มันคือวิธีการที่ทำให้เราดูราคาหุ้นแบบ realtime ได้บนหน้า web ที่เป็น HTML และทางเทคนิคตัว server ก็รับ load ได้มากด้วยการใช้ continuation ZK 3.5 ซ่อนความซับซ้อนของ Comet ไว้ใต้ programming model แบบ Thread ดังนั้นจึงแทบไม่ต้องจัดการอะไรเลย ทำแค่ active / [...]

Groovy Category ใช้งานยังไง ??

Posted September 16, 2008 at Grails66
วันนี้ผมลองนั่งดูการจัดการเกี่ยวกับเวลาใน Groovy ซึ่งพบว่าสามารถใช้ความสามารถ operator overloading ได้ง่าย เช่น ผมต้องการเพิ่มวันจากเวลาปัจจุบันไป 2 วัน ก็ทำได้ง่ายๆ ดังนี้ def current_date = new java.util.Date( System.currentTimeMillis() ) current_date += 2 ผลลัพธ์ที่ได้ Result: Thu Sep 18 18:25:48 GMT+07:00 2008 นั่งๆ เขียนไปไม่รู้อะไรมาดลใจ ให้ไปนึกถึง slide ที่คุณ @cblue ในงาน NJUG 5 เรื่องของการใช้งาน category มาช่วย ซึ่งจะทำให้ code นั้นอ่านง่ายและ เข้าใจได้ง่าย เช่นต้องการรู้คำนวณวินาทีจาก 3 hours + 20 minutes = 3*60*60 + 20*60 [...]

เขียน Groovy DSL โดยกิลโยม ลาฟอร์จ ที่ JavaZone

Posted September 17, 2008 at Grails66
DSL คือ Domain specific language หรือภาษาเฉพาะทางครับ เราเห็นกันบ่อย ๆ จากหลาย ๆ ส่วนของเกรลส์ ผมก็ทำให้ดูบ้างแล้วในเอนทรีก่อน ๆ รวมทั้งคุณ @up1 และ @virasak ก็เคยทั้งโพสต์และแสดงความเห็นไว้เหมือนกัน รวมทั้ง easyb ที่พูดถึงกันในสัปดาห์นี้ก็เป็น DSL สำหรับสนับสนุน behaviour-driven development นั่นเองครับ ภาษาเฉพาะทางภายใน หรือ internal domain specific language จะเป็นสิ่งที่เรากำลังพูดถึงกันอยู่ครับ เพราะ Groovy อนุญาตให้เราสร้าง language construct หรือโครงสร้างทางภาษาใหม่ ๆ ขึ้นมาได้ โดยมีข้อจำกัดก็แต่เพียงว่ามันจะต้องถูกต้องตามไวยากรณ์ของ Groovy ซึ่งเป็นภาษาหลัก (host language) กิลโยม ลาฟอร์จไปพูดเรื่องนี้ที่ JavaZone conference ครับ เพิ่งได้ tweet มาวันนี้เองก็เลยเอามาให้ดูกัน

หัดเล่น method_missing ใน Groovy Version

Posted September 19, 2008 at Grails66
หัดเล่น method_missing ใน Groovy Version พอไปอ่าน entry method missing ของ Rails66 แล้ว จึงคิดว่าการทำงานของ Dynamic finder ใน GORM มันน่าจะใช้แนวคิดเดียวกัน ??? ผมจึงไปค้นหาข้อมูลใน Groovy ก็เจอเอกสารอธิบายการใช้งาน methodMissing และ propertyMissing โดยความสามาถเหล่านี้จะเรียกว่า Dynamic Groovy ซึ่งประกอบไปด้วย - Dynamic Method Invocation - methodMising - MetaClass - ExpandoMetaClass มันมีหลายตัวแต่ใน entry นี้จะพูดถึง Dynamic Method Invocation และ methodMising ครับ มาเริ่มกันเลย ….. 1. Dynamic Method Invocation คือ สามารถเรียกใช้ method ที่ไม่รู้จักชื่อในขณะ [...]

มาสร้าง app สำหรับอัพโหลดรูปกัน (2)

Posted September 19, 2008 at Django66

เรามาต่อจากตอนแรกกันครับ ในตอนนี้เราจะสร้าง view และ template สำหรับแสดงรูปที่ upload มาครับ <!--break--> ผมคงไม่ลงรายละเอียดขั้นตอนมาก เอาเป็นดูเพิ่มได้จาก entry 1 2 3 ที่ sugree เขียนไว้นะครับ

มาตั้งค่าเกี่ยวกับไดเรกทอรีของ template กับจัดการตั้งค่า URL dispatcher (routing) กันก่อน

เราจะใช้ template โดยเราจะเก็บไว้ที่ youpics/templates ดังนั้นไปเพิ่มไดเรกทอรีดังกล่าวใน settings.py

TEMPLATE_DIRS = (
    # Always use forward slashes, even on Windows.
    # Don't forget to use absolute paths, not relative paths.
    "/พาธเต็ม/youpics/templates",
)

แล้วก็ไปตั้งค่า URL ในไฟล์ urls.py

เราจะเขียนฟังก์ชัน index ในโมดูล pictures.views ให้จัดการกับการเรียกหน้าหลักของเรา ดังนั้นเราจะไปเพิ่มบรรทัด

    (r'^$', 'youpics.pictures.views.index'),  # อย่าลืม "," ตรงท้าย

เข้าไปในรายการของ urlpatterns

พอตั้งค่าเรียบร้อยแล้ว ก็ได้เวลามาเขียน view และ template กันครับ

เดี๋ยวใน view เราจะโหลดวัตถุจากโมเดล Picture มา แล้วโยนให้ template นั้นแสดงผลครับ

เข้าไปแก้โค้ดใน pictures/views.py ก่อนเลยดีกว่าครับ

from pictures.models import Picture
from django.shortcuts import render_to_response

def index(request):
    pics = Picture.objects.all()
    return render_to_response("index.html",{'pictures': pics})

เราจะใช้โมเดลที่นิยามไว้ในไฟล์ models.py ในไดเร็กทอรี pictures ดังนั้นเราจึงสั่ง import จากโมดูล pictures.models ครับ

ส่วนในการเรียกให้แสดง template นั้น เราจะใช้ฟังก์ชันลัดชื่อ render_to_response เพื่อเรียกให้แสดงผล พร้อม ๆ กับส่งพารามิเตอร์เข้าไปใน template ครับ ดังนั้น ก็ต้อง import มาก่อนเช่นเดียวกัน

ในการเรียกค้นวัตถุในโมเดลใด ๆ เราจะทำผ่าน "ผู้จัดการ" (Manager) ของโมเดลนั้น ที่เข้าถึงได้ทางคลาสของโมเดลนั้น โดยทั่วไปแล้วผู้จัดการจะถูกตั้งชื่อว่า objects

ฟังแล้วดูยาก พิจารณาโปรแกรมด้านบน ในบรรทัด

    pics = Picture.objects.all()

เราเรียกเมท็อด all จาก Picture.objects ซึ่งเป็นผู้จัดการของโมเดล Picture ดังนั้น เราก็จะได้วัตถุทั้งหมดคืนมาเป็น QuerySet ซึ่งคิดง่าย ๆ (ตอนนี้) ว่าเป็นลิสต์ก็ได้

จากนั้นเราเรียก render_to_response ให้ไป render ตัว template ในไฟล์ index.html โดยส่ง pics ที่ค้นมาได้เข้าไปเป็นพารามิเตอร์ชื่อ pictures

(จริง ๆ แล้วผมอยากใช้ตัวแปร pictures ในการเก็บ QuerySet แต่ไม่อยากทำให้เข้าใจผิดว่าตัวแปรใน view จะต้องถูกส่งไปยัง template ด้วยชื่อเดียวกันครับ)

ทีนี้ไปเขียน template กัน

อย่างที่ sugree กล่าวไว้ ว่าภาษา template ของ django ไม่ใช่ xml ไม่ใช่ Python เป็นภาษาของตนเองครับ

ทีนี้ ทดลองดูจากตัวอย่างเลยครับ สร้างไฟล์ index.html ไว้ในไดเรกทอรี youpics/templates ตามด้านล่าง

<h1>YouPics</h1>

{% for picture in pictures %}
  <h3>{{ picture.title }}</h3>
{% endfor %}

ใน template นะครับ อะไรที่อยู่เครื่องหมาย {{ วงเล็บปีกกาคู่ }} จะถูกมองว่าเป็นตัวแปร และค่าของมันจะถูกแทรกลงไปในข้อความที่ render ได้

ส่วนอะไรที่อยู่ในเครื่องหมาย {% ปีกกาและเปอร์เซ็นต์ %} จะถูกเรียกว่าเป็น template tag ซึ่งจะทำให้เราสามารถควบคุมการทำงานของ template ได้

ด้านบนเราระบุให้ตัวแปร picture วิ่งไปในรายการ pictures ด้วย template tag for ภายในลูป เราสั่งให้แสดง picture.title

ลองเรียก server มาดูผลลัพธ์กันครับ

python manage.py runserver

ทีนี้เราจะทำให้มีการแสดงรูปครับ ใน ImageField ที่เราใช้เพื่อเก็บรูปนั้นมี attribute url ให้เราอ่านได้ ดังนั้นแก้ index.html เป็นดังด้านล่างครับ

<h1>YouPics</h1>

{% for picture in pictures %}
  <h3>{{ picture.title }}</h3>
  <img src="{{ picture.image.url }}"/>
{% endfor %}

แล้วลอง refresh ที่บราวเซอร์ดูครับ น่าจะเห็นรูปแล้ว

ตอนหน้าเราจะมาทำ form สำหรับ upload รูปกันครับ

Simple Login Tutorial

Posted September 21, 2008 at Grails66
back to basic กันดีกว่า ก่อนหน้านี้ไปดู Web Album on grails ก็พบว่า มันรวมหลายประเด็นเข้าด้วยกัน เลยคิดใหม่ว่า เอาหลายๆ ประเด็นนั้นมาแยกย่อยก่อนดีกว่า แล้วค่อยเอาไปประกอบกัน น่าจะดูรู้เรื่องกว่า ก่อนอื่น มาทำ login กันก่อน เราจะอิงตาม  tutorial นี้ โดยแอบเอา domain class ของเค้ามา เพราะเราขี้เกียจคิด  แต่เราจะทำตามใจเรา รวมทั้ง code ก็ต่างกันนิดหน่อยด้วย เพราะทำตามเค้ามันรันไม่ผ่านนะ ระวัง ก่อนอื่น มา create project กันก่อน grails create-app UserLogin //ตั้งชื่อโปรเจคว่า UserLogin ใครจะตั้งชื่ออื่นก็ได้ไม่ว่ากัน และก็มาสร้าง domain class โดยเราจะมี 2 domain classes คือ User และ Plant (Plant เป็นตารางตัวอย่างเหมือนกับว่าเราจะทำ login [...]

มาสร้าง app สำหรับอัพโหลดรูปกัน (3)

Posted September 22, 2008 at Django66

ต่อจากตอนที่แล้วนะครับ

ในตอนนี้เราจะหัดใช้ form ครับ ในตอนต้นเราจะเขียน form แบบธรรมดาเพื่อทดลองใช้ form และทดลองเก็บข้อมูลลงในโมเดล จากนั้นก่อนจะจบเราจะทดลองใช้ ModelForm ซึ่งทำให้การสร้างและใช้งานฟอร์มจากโมเดลทำได้ง่ายมากขึ้น <!--break--> Django มีโมดูล forms ที่ทำให้การเขียน form ที่ต้องมีการตรวจสอบข้อมูลทำได้สะดวกครับ

การใช้งานหลัก ๆ คือเราไปสร้างคลาสที่เป็นลูกหลานของ forms.Form วัตถุของคลาสดังกล่าว เมื่อนำไปแสดงใน template จะเผยตัวออกเป็น html form ที่สวยงาม จากนั้นเมื่อผู้ใช้ป้อนข้อมูลเข้ามาผ่านทาง form นั้น เราก็สามารถเอาเชื่อมข้อมูลที่ผู้ใช้ส่งมาจาก request เข้ากับวัตถุของ form เพื่อนำไปตรวจสอบความถูกต้องได้ เมื่อตรวจเสร็จเราก็จะมีข้อมูลที่เก็บกวาดแล้วไว้ใช้ (เรียกว่า cleaned_data)

เรามาประกาศ form สำหรับรับรูปกัน เพิ่มการประกาศนี้ไว้ที่ต้นไฟล์ pictures/views.py ครับ

from django import forms

class PictureForm(forms.Form):
    title = forms.CharField(max_length=100)
    description = forms.CharField(widget=forms.Textarea)
    image = forms.ImageField()

สังเกตว่าคล้ายกับการประกาศโมเดลมากครับ ยกเว้นว่าไม่มี TextField แต่เราจะใช้ forms.CharField แทน แล้วระบุว่าในเวลาแสดงผลเป็น html ให้แสดงเป็น textarea โดยกำหนดค่า widget=forms.Textarea เจ้า widget นี่คือวัตถุที่ใช้จัดการแสดงผลแต่ละ field ใน template ครับ

มีฟอร์มแล้วก็ต้องส่งไปแสดงผลที่ template

เราจะให้ผู้ใช้ upload ได้ที่หน้าแรกเลย ดังนั้นไปแก้ฟังก์ชัน index กัน โดยเพิ่มให้มีการสร้างวัตถุของคลาส PictureForm ให้เป็นฟอร์มเปล่า ๆ แล้วโยนไปให้ template แสดงผล ผ่านทางตัวแปรชื่อ form

def index(request):
    pics = Picture.objects.all().order_by('title')
    form = PictureForm()
    return render_to_response("index.html",{ 'pictures': pics,
                                             'form': form })

จากนั้นไปแก้ template index.html จากคราวที่แล้วครับ

โดยเพิ่มส่วน form เข้าไปในตอนต้นครับ

<form action="/upload/" method="POST" enctype="multipart/form-data">
  {{ form.as_p }}
<input type="submit" value="Upload"/>
</form>

สังเกตว่าการเขียน tag form ก็เขียนตามปกติ (อย่าลืม enctype="multipart/form-data") แต่ว่าส่วนที่แสดงผลฟิลด์ต่าง ๆ ในฟอร์มเราสั่งให้แสดง form.as_p ได้เลย ลองเรียก python manage.py runserver ขึ้นมาดูหน้าตากันนะครับ สังเกตว่าฟอร์มจะเบี้ยว ๆ หน่อย ถ้าเข้าไปดูที่ html จะเห็นว่าจาก form.as_p จะได้ html ประมาณนี้ครับ

<p><label for="id_title">Title:</label> <input id="id_title" type="text" name="title" maxlength="100" /></p>
<p><label for="id_description">Description:</label> <textarea id="id_description" rows="10" cols="40" name="description"></textarea></p>
<p><label for="id_image">Image:</label> <input type="file" name="image" id="id_image" /></p>

ถ้าเราไม่ชอบเบี้ยว ๆ ก็แก้ให้แสดงเป็นตารางก็ได้ครับ แก้เป็น

<form action="/upload/" method="POST" enctype="multipart/form-data">
  <table>
  {{ form.as_table }}
  </table>
  <input type="submit" value="upload"/>
</form>

พอได้หน้า template แล้ว เราก็ไปเขียนตัวจัดการกับการ upload เลยครับ

เราจะเขียนฟังก์ชัน upload ให้จัดการกับ url upload/ ดังนั้นไปเพิ่มบรรทัดด้านล่างในไฟล์ urls.py

    (r'^upload/$','youpics.pictures.views.upload'),

ส่วนโค้ดของ upload อยู่ด้านล่างครับ

def upload(request):
    if request.method == 'POST':
        # ผูก form เข้ากับข้อมูลที่ได้รับมา
        form = PictureForm(request.POST, request.FILES)
        if form.is_valid():  # ตรวจสอบข้อมูลในฟอร์ม
            # เอาค่าที่เก็บกวาดแล้วมาใช้
            title = form.cleaned_data['title']
            desc = form.cleaned_data['description']
            imagefile = form.cleaned_data['image']

            # สร้างรูปใหม่ แล้วเก็บลงฐานข้อมูล
            new_picture = Picture()
            new_picture.title = title
            new_picture.description = desc
            new_picture.image.save(imagefile.name,imagefile)
            new_picture.save()
    return HttpResponseRedirect('/')

หลัก ๆ คือถ้าผู้ใช้ส่ง request มาแบบ POST (คือส่งฟอร์มมา) เราก็จะผูกวัตถุของ PictureForm เข้ากับข้อมูลที่ได้รับ อันนี้พิเศษหน่อยที่เราต้องมี request.FILES ด้วย เพราะว่าเรามีการส่งไฟล์มา

จากนั้นเรียกเมท็อด is_valid เพื่อตรวจสอบ/เก็บกวาดข้อมูลใน form ถ้าถูกแล้วเราจะได้ข้อมูลไว้ใช้เป็น dictionary ชื่อ cleaned_data (ในการตรวจสอบความถูกต้องนี้เราสามารถเขียนเพิ่มเติมเกี่ยวกับเงื่อนได้)

ตอนท้าย ๆ เป็นการสร้างวัตถุใหม่ในโมเดล แล้วเก็บลงฐานข้อมูลครับ เราเริ่มสร้างวัตถุของคลาส Picture แล้วก็กำหนดค่าให้กับแต่ละฟิลด์เลย ที่ลำบากหน่อยคือส่วนของการเก็บรูป เพราะว่าเราต้องเก็บลงไปในที่ที่ตั้งไว้ ในขณะค่าในตัวแปร image ที่ได้มาจะอิงกับข้อมูลที่ผู้ใช้ป้อน ซึ่งอาจจะเก็บอยู่ในไดเร็กทอรีไฟล์ชั่วคราว ดังนั้นจะเอามาใช้ก็ต้องสั่ง save เอาเองที่ฟิลด์นั้นครับ (ในเอกสารเก่าหน่อยจะให้สั่ง save_FIELD_file แต่มัน deprecated ไปแล้ว)

สุดท้ายเราสั่ง HttpResponseRedirect ให้ browser redirect กลับไปหน้าแรก จะสั่งฟังก์ชันนี้ได้อย่าลืมใส่บรรทัดด้านล่างไว้ตรงหัว views.py นะครับ

from django.http import HttpResponseRedirect

เท่านี้ก็เรียบร้อยครับ ทดลองเล่นได้ครับ

ที่เราทดลองมานี่เป็นการทำแบบอ้อม ๆ ครับเพื่อแสดงให้เห็นการใช้งาน Form อย่างง่ายครับ แต่จริง ๆ แล้ว ถ้าเราต้องการสร้างฟอร์มจากโมเดล เรามีคลาสช่วยเหลืออย่าง ModelForm ทำให้เขียนง่ายขึ้นมากครับ ด้านล่างเป็น views.py ในส่วนประกาศ PictureForm และฟังก์ชัน upload ที่เขียนโดยใช้ ModelForm ครับ

class PictureForm(ModelForm):
    class Meta:
        model = Picture  # สร้าง form จากโมเดล Picture

def upload(request):
    if request.method == 'POST':
        # ผูกฟอร์มเข้ากับข้อมูล
        form = PictureForm(request.POST, request.FILES)
        if form.is_valid():    # ทดสอบความถูกต้อง
            form.save()        # เก็บ
    return HttpResponseRedirect('/')

ส่วนที่หายไปก็คือการประกาศฟิลด์ตามโมเดล และส่วนการจัดการเรื่อง save ครับ

ที่นี้ก่อนจบมาเก็บกวาดกันต่ออีกสักนิดครับ

สังเกตว่าในโมเดลเรามีฟิลด์ description แต่ไม่ได้เอาไปแสดงผลเลย ถ้าต้องการแสดงก็แก้ส่วน template โดยเพิ่มให้แสดง {{ picture.description }} เข้าไปนะครับ ทีนี้ ถ้าเราพิมพ์หลาย ๆ บรรทัดแล้วเราต้องการให้มีการแปลงเครื่องหมายขึ้นบรรทัดใหม่ให้เป็น <br> ให้ใส่เป็น {{ picture.description|linebreaks }} แทน ส่วน |linebreaks เป็น filter ให้เราปรับแต่งการแสดงผลของตัวแปรได้ครับ

ปรับเอาตามชอบเลยนะครับ ตัวอย่างด้านล่างนี่แสดงรูป (ย่อเหลือความกว้าง 100) แล้วแสดงคำอธิบายข้าง ๆ ครับ

{% for picture in pictures %}
  <h3>{{ picture.title }}</h3>
  <table>
    <tr><td>
      <img src="{{ picture.image.url }}" width="100"/>
    </td><td>
      {{ picture.description|linebreaks }}
    </td></tr>
  </table>
{% endfor %}

ส่วนของ tutorial การเขียน app เพื่ออัพโหลดรูปคงจบไว้คร่าว ๆ แค่นี้ครับ (อาจมีตอนต่อไปอีกได้ เกี่ยวกับการทำ user และทำเรื่องการ follow)

เอกสารเพิ่มเติม

  • ดูรายละเอียดเกี่ยวกับ file upload
  • เอกสาร ModelForm

RESTful with Grails

Posted September 24, 2008 at Grails66
RESTful with Grails วันนี้ไปอ่านเจอบทความเรื่อง Mastering Grails: RESTful Grails ประจวบเหมาะกับหลายๆ วันที่ผ่านมาผมนั่งทำแต่ services api ที่มี data exchange format เป็น XML, JSON ผ่าน GET/POST HTTP เลยมองมาดูที่ตัว Grails ว่าสนับสนุนการทำงานเช่นเดียวกับที่ผมทำอยู๋หรือเปล่า อย่างไร และที่สำคัญมันง่ายไหม ?? ….. ซึ่งพบว่า Grails นั้นได้เตรียมสิ่งต่างๆ ไว้ให้ ใช้งานสะดวกมาก ถูกใจวัยรุ่นอย่างผมมาก … ^_^ เรามาเริ่มดูการสร้าง XML และ JSON โดยการใช้ API grails.converters.* ซึ่งเป็น APIs ที่ Grails จัดเตรียมไว้ให้ ตัวอย่างการใช้งาน $grails create-domain-class Book class Book { String title Integer [...]

การจัดการ GORM Relationship แบบ Many-to-Many

Posted September 28, 2008 at Grails66
หลังจากที่ผ่านมาได้พูดถึงการจัดการ GORM Relationship แบบ One-to-Many กันแล้วมา entry นี้จะมาพูดถึงการจัดการความสัมพันธ์แบบ many-to-many กันบ้าง เริ่มกันเลย …….. ในการจัดการความสัมพันธ์แบบนี้ โดยทั่วไปนั้นจะสร้าง table กลางขึ้นมาเพื่อเชื่อมความสัมพันธ์กันดังรูป ซึ่งจะมองได้ว่าเป็นมีความสัมพันธ์ขึ้นดังนี้ BookWriter –> Book BookWriter –> Writer เมื่อมาจัดการความสัมพันธ์ลักษณะนี้ใน GORM สามารถทำได้ง่าย โดยจุดสำคัญอยู่ที่ domain class : BookWriter จะเป็นตัวเชื่อมความสัมพันธ์ของ Book และ Writer ดังนี้ Book.groovy class Book { String name } Writer.groovy class Writer { String name } BookWriter.groovy import Writer class BookWriter { static belongsTo = [ book:Book, writer:Writer ] } คำอธิบาย static belongsTo = [ book:Book, writer:Writer ] [...]

Looping with Groovy

Posted October 03, 2008 at Grails66
ใน rails มี entry เกี่ยวกับ looping Loop 9 แบบบน ruby แล้ว grails66 จะยอมน้อยหน้าได้อย่างไร ดังนั้นมาดูกันว่า Looping ใน Groovy สามารถเขียนอย่างไรได้บ้าง ลอกจากเอกสารของ Groovy มาตรงๆ และแก้กันหน้าด้านๆ เลยครับ ขอเน้น coding นะครับ ไม่เน้นอธิบาย เพราะว่า code อธิบายตัวเองอยู๋แล้ว ^_^ 1. While loop while( ) { } เช่น def x = 0 while( x++ < 5 ) { println x } 2. For loop Syntax ที่เป็นพื้นฐานสุดๆ คือ for( ค่าเริ่มต้น; เงื่อนไขการทำงาน; [...]

ทำความรู้จักกับ Android

Posted October 06, 2008 at Android66

Android คือระบบปฏิบัติการ (Operating System) บนโทรศัพท์มือและอุปกรณ์พกพาที่พัฒนาโดย Google. เราอาจเรียก Android เป็น Software Stack ที่ประกอบด้วย ระบบปฏิบัติการ โปรแกรมต่างๆ และแฟรมเวิร์ค (Framework) สำหรับนักพัฒนา เพื่อใช้ในการพัฒนาโปรแกรมบนแพลตฟอร์ม Android ได้

สถาปัตยกรรมของ Android
จากรูป Android จะประกอบด้วย องค์ประกอบหลักอยู่ 5 ส่วน ดังนี้

1. ซอฟแวร์ทั่วไป (Applications)
อุปกรณ์พกพาที่ติดตั้ง Android จะมาพร้อมโปรแกรมหลักที่ไว้ใช้งานทั่วไป เช่น โปรแกรมรับส่งอีเมล, SMS, ปฏิทิน, แผนที่, Browser (ใช้ WebKit เป็น Engine) เครื่องมือจัดการสมุดโทรศัพท์ และโปรแกรมหลักอื่นๆ

2. แฟรมเวิร์ค (Application Framework)
นักพัฒนาสามารถพัฒนาโปรแกรมบน Android โดยใช้ภาษา Java ผ่านทาง API (Application Programming Interface) โดยสามารถเข้าถึงระบบและข้อมูลต่างๆ ที่อยู่บน Android ดังนี้

  • Views ประกอบด้วย UI ชนิดต่างๆ ที่ใช้ในการพัฒนาโปรแกรม เช่น lists, grids, text boxes, buttons รวมไปถึง Event และเว็บบราวเซอร์
  • Content Provider โปรแกรมที่พัมนาบน Android จะสามารถส่งข้อมูลถึงกันผ่านทาง Content Provider เช่นเราสามารถพัฒนาโปรแกรมเพื่อไปดึงข้อมูลรายชื่อที่อยู่ใน Contacts ได้
  • Resource Manager เป็นตัวจัดการเรื่องรูปภาพ, Localized strings และข้อมูลอื่นๆ ที่นอกเหนือจาก Code ของโปรแกรม
  • Activity Manager นักพัฒนาสามารถสร้าง Custom Alert และส่งไปแสดงผลที่ Status Bar โดยผ่าน Activity Manager

3. ชุดพัฒนา (Libraries)
Android ยังประกอบด้วยชุดพัฒนาของ C/C++ อื่นๆ ที่สามารถใช้งานผ่านทาง API ของเฟรมเวิร์คที่ Android ได้จัดไว้ให้ (API เป็นภาษา Java)

  • System C Library ไลบรารีมาตรฐานของ C (C system library) ปรับปรุงพิเศาสำหรับอุปกรณ์ที่รันบน Linux
  • Media Library โดย Android สรับสนุนการใช้งานไฟล์ฟอร์แมตต่างๆ เช่น MPEG4, H.264, MP3, AAC, AMR, JPG และ JPG
  • Surface Manager เป็นตัวจัดการระบบแสดงผล และควบคุมบนจอภาพ

read more

OFBiz กับ Groovy ตอนที่ 1

Posted October 09, 2008 at Ofbiz66
เรียกว่าข้ามกำแพงภาษาได้ยังเนี่ย แ่ต่ที่รู้แน่ๆ ข้ามกลุ่มกันเห็นๆ ofbiz66 และ grails66 ^O^ พอดีไปอ่าน ofbizguru มา คุณ him_aeng บอกเกี่ยวกับ groovy tutorial on OFBiz ก็เลยว่าจะอ่านดูซะหน่อย ไหนๆ ก็อ่านแล้ว เขียนไว้ด้วยเลยก็แล้วกัน จะได้เป็น groovy tutorial in Thai version เผื่อจะเป็นประโยชน์กับหลายๆ คนค่ะ tutorial นี้เอามาจาก official website ของ OFBiz เองเลย เค้าเขียนไว้ทั้งหมด 19 ข้อ เก๋ขอไล่สำหรับ blog นี้ 5 ข้อ ก่อนละกัน เดี๋ยวจะง่วงเกินไป 1. ไฟล์สำคัญที่ใช้กับ groovy ใน OFBiz มีดังต่อไปนี้ GroovyUtil.java GroovyServiceTest.groovy GroovyEngine.java ModelFormAction.java และ jar files ที่เกี่ยวข้องกับการ run groovy [...]

การแปลง AST - ฟีเจอร์ใหม่ใน Groovy 1.6-beta : เรื่องของ @Singleton

Posted October 10, 2008 at Grails66
AST Transformation หรือการแปลง AST เป็นฟีเจอร์ของ Groovy ที่จะทำให้ชีวิตเราง่ายขึ้นไปอีกระดับครับ การแปลง AST จะใช้ annotation (ซึ่งมากับ Java 5) ในการกำหนดความหมายของสิ่งที่ต้องการแปลง โดยขั้นตอนในการคอมไพล์จะเป็นประมาณนี้ครับ source code เดิม -> ตรวจสอบ annotation -> แปลง AST -> source code ใหม่ -> สร้างเป็น .class -> เอาไปใช้งาน ในเอนทรีนี้ผมยกตัวอย่างการใช้ @Singleton เป็นตัวแรกครับ โดย @Singleton นั้นแสดงถึงการกำหนด Singleton Pattern ให้กับคลาส ในกรณีที่เราต้องการ share วัตถุของคลาสดังกล่าวกับทุก ๆ reference (ผมไม่เชี่ยวชาญด้าน Design Pattern มากนัก การอธิบายความหมายอาจจะไม่ตรงเป๊ะ ๆ นะครับ) คราวนี้มาดูกันว่า @Singleton ใน [...]

VDO :: How To Do AJAX With Grails in NetBeans

Posted October 30, 2008 at Grails66
ไม่ได้มาโฆษณา NetBeans นะครับแต่ขอ นำเสนอ VDO การใช้งาน AJAX ใน Grails Application ครับ น่าสนใจดีครับเลยเอามาฝาก ใน VDO ใช้ NetBeans IDE 6.5 RC ครับ ที่มา :: http://netbeans.tv/screencasts/How-To-Do-AJAX-With-Grails-412/ ========= ข่าวแอบแปะ ========= - GRAG ( The GRails Application Generator ) ออก version 1.0 มาแล้วนะครับ - Grails for PHP developers part 1 , part 2 - จาก Talk66 Episode 3 ได้พูดถึง GroovyMag สนใจเข้า [...]

เรียนรู้ Grails ด้วย Login Application

Posted November 07, 2008 at Grails66
ได้รับ dm มาจากคุณ @NAzT เกี่ยวกับการแนะนำ เนื้อหาและบทความใน Grails66.com ดังนี้ - อยากเสนอให้เขียนบทความของ grails66 ระดับ basic ครับผม อย่างเช่น การส่งค่า และเรียกใช้ค่าไปมาระหว่าง controller และ view เป็นต้นครับ - เพราะเท่าทีสังเกต มือใหม่จะไม่ค่อยเข้าใจน่ะครับ ว่าจะเรียกใช้ หรือส่งค่าไปมาอย่างไร ทำให้คิดต่อไม่ได้ครับ - ส่วนเพื่อนๆที่ไม่เคยใช้ mvc มาก่อน จะไม่รุ้ว่าจะเอาค่าจาก form ไปใช้ต่อยังไงน่ะครับผม ผมกลับมาดูบทความต่างๆ ก็เป็นจริงตามนั้น ดังนั้นผมจึงขอเริ่มด้วยบทความง่ายๆ หรือเบื้องต้นสำหรับมือใหม่ ผมก็มือใหม่เช่นกันครับ ผมจะใช้ tag บทความว่า newbie เพื่อให้ง่ายต้อการค้นหาครับ โดยผมจะเริ่มตั้งแต่ Login Application ก่อนแล้วกันนะครับ เป้าหมายเพื่อ - เข้าใจ MVC Model - เข้าใจการสร้าง Grails Framework ด้วยแนวคิด MVC Flow ของระบบ - [...]