Grails66 Quickpod ตอนพิเศษ เริ่มใช้ Voice Mail

Posted September 12, 2008 at Grails66
Quickpod ตอนพิเศษ 1: เริ่มใช้ Voice Mail ดาวน์โหลด mp3 โทรเข้ามาฝากข้อความแสดงความคิดเห็นผ่านระบบ voicemail ของ Skype ได้ที่ chanwit.kaewkasi หรือคลิ๊กที่ไอค่อนโทรศัพท์ครับ สำหรับท่านที่ไม่มี Skype สามารถโทรศัพท์มาได้ที่ +1-650-209-6449 (California, USA) แนะนำให้ใช้ 009 ครับเพื่อความประหยัดครับ

easyb ง่ายจริงหรือ ?

Posted September 17, 2008 at Grails66
Meera Subbarao เขียนบทความเรื่องนี้ไว้บน Groovy DZone ครับ http://groovy.dzone.com/articles/is-easyb-easy ลองอ่านกันดูแล้วจะรู้ว่า easyb ง่ายอย่างที่ชื่อเขาบอกไว้หรือไม่

BDD ภาษาไทย

Posted September 18, 2008 at Grails66
ผมเชื่อว่ายังมีแรงต้านกันอยู่พอสมควรที่จะใช้ภาษาไทยในการเขียนโปรแกรม เพราะมันเป็นเรื่องจริงครับ ที่ภาษาไทยไม่เหมาะเลยที่จะใช้เป็นภาษาโปรแกรมด้วยหลาย ๆ เหตุผล ตั้งแต่การใช้สัญลักษณ์ ไปจนถึงการใช้คำ เพราะภาษาไทยเป็นภาษาสื่อสาร เราจึงควรใช้มันให้เหมาะเพื่อการสื่อสารครับ ตามที่เคยพูดไว้ใน quickpod ว่า BDD มีจุดพิเศษตรงที่มันเป็นความพยายามจะรวมเอา ภาษาสื่อสารกับภาษาโปรแกรมมาใช้ร่วมกันให้เกิดประโยชน์มากขึ้น ซึ่งอาจจะไม่ชัดเจนนักในภาษาอังกฤษ เพราะเส้นกั้นระหว่าภาษาโปรแกรมเช่น Groovy หรือ Java กับภาษาอังกฤษนั้นมันค่อนข้างเบลอ แต่กับภาษาไทย เราเห็นชัดเจนครับว่ามันต่างกัน ภาษาไทยในโค้ดจะไม่มีประโยชน์เลย ถ้าเราให้คนที่อ่านภาษาโปรแกรมออกมาอ่านโค้ดดังกล่าว แต่มันกลับกลายเป็นว่าจะมีประโยชน์มาก เมื่อคนที่ไม่คุ้นเคยกับภาษาโปรแกรม มาเห็นโค้ดชุดนั้น ผมเคยทดสอบเรื่องนี้ไว้ใน narisa.com เสียดายที่ช่วงนี้ server down เลยไม่ได้มีโอกาสไปค้นกระทู้มาอ้างอิง จากจุดนั้นผมเลยเริ่มมีความเชื่อว่า จริง ๆ แล้วการใช้ภาษาไทยร่วมกับภาษาโปรแกรมนั้นมีประโยชน์ ถ้าเราใช้ให้เหมาะสม นี่คือที่มาของ tspec ซึ่งเป็น BDD framework ที่สนับสนุนภาษาไทย แต่ไม่ได้ให้ developer เขียนโค้ดภาษาไทยครับ เกริ่นมานานก็เอาโค้ดมาให้ดู เรื่อง 'ภาษี' อธิบาย 'การมาจ่ายภาษีครั้งแรก', { กำหนดให้ 'มีผู้มาจ่ายภาษีชื่อสมชาย', { name = 'สมชาย' } เมื่อ 'เป็นการมาจ่ายครั้งแรก', { payer = Payer.findByName(name) } แล้วควร 'จะไม่พบข้อมูล', { payer.shouldBe [...]

มาสร้าง 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 รูปกันครับ

ตั้งค่า path ใน settings.py แบบ relative

Posted September 21, 2008 at Django66

ในการตั้งค่าในไฟล์ settings.py สิ่งที่น่ารำคาญอย่างหนึ่งก็คือการต้องระบุ path แบบเต็ม (absolute) เพราะทำให้เวลาย้ายไดเร็กทอรีของ project ไปที่อื่นแล้วมันต้องแก้เยอะ

วันนี้ไปอ่านมาจาก Tutorial Django From the Ground Up: Episodes 1 and 2 เจอวิธีดี ๆ ครับ (ซึ่งก็ตรงไปตรงมา ทำไมเราไม่นึกได้เองนะ) เขาให้ใส่

import os.path
PROJECT_DIR = os.path.dirname(__file__)

ไว้ที่ต้นโปรแกรม <!--break--> ทีนี้เวลาจะอ้างถึงไดเร็กทอรีก็เอา PROJECT_DIR แปะตอนต้นเสียก่อนเช่น

TEMPLATE_DIRS = (
    PROJECT_DIR + "/templates",
)

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

มาสร้าง 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

ใช้ resource.groovy เพื่อประกาศ Spring Bean

Posted September 24, 2008 at Grails66
กำลังสาละวนอยู่กับโปรเจ็คนึงอยู่ และกำลังจะเริ่มเตรียมการทดสอบแบบอัตโนมัติ แต่พอดีไปสะดุดตาเข้ากับการประกาศ Spring Bean ด้วย bean builder แทนการใช้ XML ครับ เลยหยิบมาเป็นประเด็น ซึ่งคิดว่าน่าจะมีประโยชน์ โดยปกติผู้ใช้ Spring จะประกาศ bean ด้วย XML เพื่อเตรียม bean ที่ต้องการจะ inject เข้าสู่ตัวระบบงาน (อ่านเพิ่ม Dependency Injection Pattern) ในเกรลส์เราทำได้ผ่าน resource.xml และถ้าไม่อยากเขียน XML (ซึ่งเป็นวิธีที่ผมกำลังจะเล่าให้ฟัง) ก็ทำได้โดยการระบุ Spring Bean เป็นภาษา Groovy ลงใน resource.groovy ครับ ภาษาที่ใช้กำหนด Spring Bean ก็เรียกกันว่า bean DSL ถ้าเราเขียน XML แบบนี้ ใน resource.groovy เราสามารถเขียนได้เป็น myBean(my.company.MyBeanImpl) จะเห็นว่า สั้นกระชับกว่าเยอะเลยครับ ถ้าต้องการที่จะกำหนด property ลงใน bean [...]

Template inheritance

Posted September 27, 2008 at Django66

ความสามารถที่น่าสนใจของ template ใน django อีกอย่างหนึ่ง (นอกจากความเข้มงวดในการใช้ code ใน template) ก็คือ template inheritance

อธิบายง่าย ๆ ก็คือความสามารถที่ template จะสืบทอดหน้าตามาจาก template อื่น ๆ แล้วก็ปรับแต่งเฉพาะส่วนที่ต้องการ ซึ่งใน django แต่ละส่วนใน template ที่ปรับแต่งได้นี้จะเรียกว่า block <!--break--> ดูตัวอย่างดีกว่าครับ ด้านล่างเป็น template ชื่อ base.html สังเกตว่าเราเปิดการประกาศ block ด้วย tag block พร้อมด้วยชื่อ แล้วปิดด้วย endblock

<html>
<body>
<h1>{% block title %}Sample Application{% endblock %}</h1>
<div style="border: 1px dashed black; background: #dddddd">
  {% block subtitle %}
    This application shows template inheritance
  {% endblock %}
</div>

{% block body %}
  <p>
    This is the first page. you'd probably don't like it.
    Try <a href="{% url template.sample.views.user %}">this</a>.
  </p>
{% endblock %}

<p>
  Some more stuff that won't change.
</p>

</body>
</html>

ในตัวอย่างข้างต้นได้ประกาศ block ไว้สาม block คือ title, subtitle และ body

สังเกตว่าใน template ข้างต้นมีการเรียกใช้ tag url เพื่อสร้าง url ของฟังก์ชันที่ต้องการ โดยในการสร้างจะใช้การตั้งค่าที่เราระบุไว้ใน urlpatterns การระบุ url แบบนี้ทำให้เราสามารถเปลี่ยนการ map url ได้โดยไม่ต้องแก้ template

หน้า template นี้เมื่อ render ก็จะแสดงผลตามปกติ ดังด้านล่าง

ทีนี้ เราสามารถสร้างอีก template หนึ่งให้เรียกใช้ template ข้างต้นได้ โดยใช้ tag extends จากนั้นถ้าต้องการแก้ block ใด ก็ประกาศ block เหล่านั้นเสียใหม่ ส่วน block ที่เราไม่ได้ประกาศก็จะไม่มีการเปลี่ยนแปลง

Template ด้านล่างประกาศ block subtitle และ body ใหม่

{% extends "base.html" %}

{% block subtitle %}
  You are in user page.
{% endblock %}

{% block body %}
  <p>
    You see that this text changes
    and the subtitle changes.
    The title and the text below remain the same..
  </p>
{% endblock %}

ซึ่งแสดงผลเป็น

ความสามารถนี้เป็นที่ถูกอกถูกใจหลายคน เพราะว่าเราสามารถแบ่ง template ให้เป็นส่วน ๆ เพื่อการปรับแต่งได้ง่ายมาก นอกจากนี้การ inheritance ยังทำได้หลายทอด โดยจะสืบทอดกันไปกี่ทอดก็ได้

หน้าเฉพาะผู้ใช้ที่ลงทะเบียนแล้ว

Posted October 01, 2008 at Django66

Django มาพร้อมกับ app มาตรฐาน django.contrib.auth ที่จัดการเกี่ยวกับผู้ใช้ (การ login การจัดการเกี่ยวกับเข้าถึงหน้าต่าง ๆ) ที่ใช้งานได้ไม่ยาก โดยปกติแล้วตัว app นี้จะถูกติดตั้งมากับโครงงานของเราโดยอัตโนมัติเมื่อเริ่มสร้าง

ในตอนนี้ เราจะใช้ django.contrib.auth เพื่อสร้างการจัดการผู้ใช้อย่างง่าย สำหรับโปรแกรมประยุกต์ที่มีหน้าพิเศษที่ต้องการให้เฉพาะ user ที่มีในระบบเท่านั้นเข้าได้

เกี่ยวกับเรื่องนี้เรามีเอกสารอ้างอิงหลักคือ: User authentication in Django

read more

OFBiz คืออะไร?

Posted October 01, 2008 at Ofbiz66
Apache OFBiz foundation ได้ให้นิยามของ OFBiz เอาไว้ว่า OFBiz เป็น โครงการสร้าง open source enterprise automation ที่อยู่ภายใต้ลิขสิทธิ์ของ Apache License version 2.0 โดย Open source enterprise automation เราจะหมายถึง Open source ERP, Open source CRM, Open source E-business/E-commerce, Open source CRM, Open source MRP, Open source CMMS/EAM และอื่นๆ OFBiz มี module สำหรับธุรกิจทั่วไปที่สามารถนำไป reuse เพื่อใช้งานได้ และมีแนวทางเพื่อการพัฒนาหลายรูปแบบสำหรับผู้ที่ต้องการปรับแต่ง business logic และต่อกับระบบภายนอก และนอกจากนั้น OFbiz ทำให้ค่าใช้จ่ายในการพัฒนาลดลง [...]

ติดตั้งเพื่อใช้งาน OFBiz

Posted October 01, 2008 at Ofbiz66
ไหนๆ ofbiz66 ก็เพิ่งจะเปิดตัว เรามาเริ่มกันที่การติดตั้งเพื่อใช้งานก่อน เพื่อเป็นประโยชน์กับผู้ที่เพิ่งมาใหม่ค่ะ โดยเอกสารนี้จะอ้างอิงมาจาก official website ของ OFBiz และจาก OFBizguru ค่ะ Quick & Easy Setup ดาวน์​โหลด​และ​ติดตั้ง​ Java 2 v1.4 ​หรือ​ v1.5 series JDK/J2SDK ​(​ไม่​ใช่​ตัว​ JRE, ​ผู้​ใช้​ต้อง​การ​ SDK ​ตัวเต็ม) ​จาก​ไซต์ของ​ Sun’s Java (J2SE) ​และ​ตรวจสอบ​ให้​แน่​ใจตัวแปร​ JAVA_HOME environment ​ได้​ set ​ไป​ยัง​ JDK ​ตัวนี้หลัง​จาก​การติดตั้ง​ (หมายเหตุว่าสำ​หรับ​ Mac OS X ​ไม่​ต้อง​มีการ​ setup JVM ​แค่​แน่​ใจว่า​ Java ​เป็น​เวอร์ชั่นอัพเดท​กับ​ OS X Software Update facility) ดาวน์​โหลด​ OFBiz [...]

มาลองสร้าง domain classes ด้วย GRAG v.1.0

Posted October 06, 2008 at Grails66
ไปอ่านข่าวเจอที่นี่ครับ The GRails Application Generator (GRAG) v1.0 released เลยอยากรู้ว่ามันคืออะไร และใช้งานอย่างไร :: มาเริ่มกันเลยครับ :: GRAG [ GRails Application Generator ] เป็น GUI tools สำหรับการสร้าง domain classes จาก Table/Database ที่มีอยู่แล้ว  หรือการทำ reverse engineer นั่นเอง เป็นลักษณะการพัฒนาที่หลีกเลี่ยงยากได้พอสมควร [ ยกเว้น project ใหม่จริงๆ ] GRAG นั้นจึงเป็นเครื่องมือที่เข้ามาช่วยให้สร้าง domain classes ได้ง่ายขึ้น [ หลายๆ คนอาจจะเขียน domain classes ขึ้นมาเอง เหมือนผม ] แล้ว GRAG [...]

ทำความรู้จักกับ 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

JSR 166y กับ Groovy

Posted October 10, 2008 at Grails66
JSR 166y กับ Groovy 1. JSR 166y คืออะไร jsr166y adds a lightweight task framework known as ForkJoin (FJ) to the Java platform. It is targeted for Java 7. 2. ForkJoin (FJ) คืออะไร ถ้าอธิบายง่ายๆ คือ - แบ่งงานกันทำ - รอจนทุกงานสำเร็จ - รวมผลลัพธ์จากการทำงานเข้าด้วยกัน Algorithm ที่ผู้พัฒนาเขาเขียนไว้เป็น pseudocode ดังนี้ Result solve( Problem problem ) { if( problem is small ) { directly solve problem } else [...]

include tag และ ajax

Posted October 10, 2008 at Django66

วันก่อนโน้นเขียนเรื่อง partials ใน rails66 ใน Django ก็มีความสามารถคล้าย ๆ กันอยู่ คือ include tag ซึ่งนอกจากจะทำให้ template เราอ่านง่ายแล้วหลายครั้งยังทำให้เขียน ajax ได้ง่ายด้วย

read more

ตกแต่ง Pagination ด้วย Inclusion Tags

Posted October 17, 2008 at Django66

จากบันทึก "ทำ simple tag ใช้เอง" ของ @jittat คราวก่อน ทำให้เราพอจะเห็นภาพของ custom tag ชนิดแรกไปบ้างแล้ว คราวนี้ลองมาดูอีกชนิดหนึ่ง ซึ่งก็คือ inclusion tag ครับ

และจากบันทึกก่อนหน้านี้ "include tag และ ajax" ทำให้เราพอจะสรุปง่ายๆ ได้ว่า

simple tag + include tag = inclusion tag

นั่นก็คือ inclusion tag มันทำงานเหมือน simple tag แต่ต้องการ template เพื่อมาแสดงผลลัพธ์

สาเหตุที่ทำให้ต้องมาใช้ inclusion tag คือผมต้องการทำ [pagi

read more

settings.py สำหรับพัฒนากับสำหรับการ deploy

Posted October 25, 2008 at Django66

หลายครั้งเราต้องการกำหนดค่าเริ่มต้นที่แตกต่างกันใน settings.pyสำหรับใช้ในการพัฒนาและในการ deploy ยกตัวอย่างเช่นพวก MEDIA_URL หรือ ADMIN_MEDIA อะไรประมาณนี้

วิธีที่ผมใช้ส่วนมากก็คือสร้าง settings.py ไว้สองอันแยกกัน เวลา deploy ก็อย่าเอาไฟล์นี้ไปทับกัน (อาจทำได้โดยไม่ใส่ไฟล์ดังกล่าวไว้ใน version control system) แต่วิธีนี้มักมีปัญหาว่า บางทีเราแก้ค่าเริ่มต้นบางอย่างที่ส่วนมากจะใช้ร่วมกัน เช่น เพิ่ม APPS เราก็ต้องแก้ทั้งสองไฟล์ แล้วบางทีก็ลืม

วันนี้ไปอ่านอีกวิธีเจอมาใน django user group ใน google groups เลยเอามาเขียนบอกต่อกันครับ

read more

ชื่อ django

Posted November 08, 2008 at Django66

หลายคนคงทราบแล้วว่าชื่อ django นี้มาจากชื่อ Django Reinhardt นักกีตาร์แนว gypsy jazz

วันนี้ผมเพิ่งไปเจอว่า Adrian Holovaty หนึ่งในนักพัฒนาแรกเริ่ม (และเป็น BDFL) ของ django ไปแสดงกีตาร์อยู่ที่ YouTube มากมายหลายคลิป แน่นอนว่าเป็นแนว gypsy jazz (เจอจาก TWiD)

หนึ่งในนั้นน่าจะถูกใจหลายคน Super Mario Bros. 2 theme, gypsy style ฟังเพลงอื่น ๆ ของเขาได้ที่ http://holovaty.com/music

read more

ชื่อ django กับ Super Mario Bros. 2 theme

Posted November 08, 2008 at Django66

หลายคนคงทราบแล้วว่าชื่อ django นี้มาจากชื่อ Django Reinhardt นักกีตาร์แนว gypsy jazz

วันนี้ผมเพิ่งไปเจอว่า Adrian Holovaty หนึ่งในนักพัฒนาแรกเริ่ม (และเป็น BDFL) ของ django ไปแสดงกีตาร์อยู่ที่ YouTube มากมายหลายคลิป แน่นอนว่าเป็นแนว gypsy jazz (เจอจาก TWiD)

หนึ่งในนั้นน่าจะถูกใจหลายคน Super Mario Bros. 2 theme, gypsy style ฟังเพลงอื่น ๆ ของเขาได้ที่ http://holovaty.com/music

read more

แก้ปัญหา Android plugin บน Ubuntu Gutsy

Posted November 16, 2008 at Android66

เขียนไว้นานแล้วใน atthakorn.com คิดว่าน่าจะเอามารวมไว้ที่นี่เลยดีกว่า

ลองลง Android plugin บน Eclipse จะทดสอบรันโปรแกรม Sample ที่กับชุดพัฒนา Android พบว่าไม่สามาถทำงานได้ นั่งหาทางแก้ไขอยู่สักพัก พบว่าเจ้าตัว Android plugin ไม่สามารถทำงานบน Eclipse รันบน GCJ JVM ได้ ถ้าใครเจอปัญหาเดียวกันนี้ก็ให้ลองตรวจสอบ Default VM ของ Eclipse ได้โดยเปิดโปรแกรม Eclipse แล้วเลือก Help -> About Eclipse SDK -> Configuration details จะพบข้อมูลดังนี้

[...] -vm /usr/lib/jvm/java-gcj […] 

จะเห็นว่า Default VM ของ Eclipse เป็น GCJ JVM ซึ่งเป็นเหตุผลที่ทำให้เจ้าตัว Android Plugin ทำงานได้ไม่เต็ม 100% วิธีแก้ไขก็ให้เราไปเปลี่ยนลำดับ JVM ที่เป็นของ Sun ให้อยู่บนสุดในไฟล์ /etc/eclipse/java_home ดังนี้

# This file determines the search order the Eclipse Platform uses to find a # compatible JAVA_HOME. This setting may be overridden on a per-user basis by # altering the JAVA_HOME setting in ~/.eclipse/eclipserc. /usr/lib/jvm/java-6-sun /usr/lib/jvm/java-gcj 

หลังจากแก้ไขแล้วให้ลองตรวนสอบที่หน้า Help ของ Eclipse อีกที Default VM จะต้องเปลี่ยนไปตามค่า Configuration ที่ได้แก้ไปสักครู่ แล้วก็ลองไปทดสอบรันโปรแกรมตัวอย่างของ Android อีกครั้งพบว่าตอนนี้โปรแกรมสามารถทำงานได้แล้ว