Sunday, September 26, 2010

Learning Django: Form

การสร้าง form เป็นเรื่องจำเป็นสำหรับ web app ทั่วไป ในหัวข้อนี้จะกล่าวเกี่ยวกับเรื่อง Form ใน Django

Getting Data from the Request Object

เราสามารถรับค่าจาก request object (browser) ได้ ใน view แต่ละ view จะมี HttpRequest เป็นพารามิเตอร์แรก ลองดูตัวอย่าง hello view ของเรา


from django.http import HttpResponse
def hello(request):
    return HttpResponse("Hello world")

ในตัว request มี attributes และ methods ดังนี้
- request.path
- request.get_host()
- request.get_full_path()
- request.is_secure()
- request.META เป็น python dictionary ปกติจะมี ข้อมูลดังนี้
    - HTTP_REFERER
    - HTTP_USER_AGENT
    - REMOTE_ADDR
- request.GET เป็น python dictionary
- request.POST เป็น python dictionary


Form example

เราลองมาสร้าง form จาก application ของเรากันดู



1. สร้าง template search_form.html โดยมี input ประมาณนี้

<form action="/search/" method="get">
<input type="text" name="q">
<input type="submit" value="Search">
</form>


2. สร้าง template สำหรับ search_results.html

<p>You searched for: <strong>{{ query }}</strong></p>
{% if books %}
<p>Found {{ books|length }} book{{ books|pluralize }}.</p>
<ul>
{% for book in books %}
<li>{{ book.title }}</li>
{% endfor %}
</ul>
{% else %}
<p>No books matched your search criteria.</p>
{% endif %}

3. สร้าง view สำหรับ input form และ search ใน books/views.py

from django.http import HttpResponse


from django.shortcuts import render_to_response



from mysite.books.models import Book


def search_form(request):
    return render_to_response('search_form.html')



def search(request):
    if 'q' in request.GET and request.GET['q']:
        q = request.GET['q']
        books = Book.objects.filter(title__icontains=q)
        return render_to_response('search_results.html',
        {'books': books, 'query': q})
    else:
        return HttpResponse('Please submit a search term.')

3. map input form และ search ใน urls.py




urlpatterns = patterns('',
    # ...
    (r'^search-form/$', views.search_form),
    (r'^search/$', views.search),
    # ...
)


ลองมาดูตัวอย่างที่ซับซ้อนขึ้น เราจะสร้าง contact form โดยมีลักษณะดังนี้


1. สร้าง contact_form.html ที่เป็น template สำหรับกรอกข้อมูล
2. contact_form.html ส่งข้อมูลไปยัง contact
3. contact ตรวจสอบข้อมูล
    -ถ้าไม่มีข้อผิดพลาดส่งเมลล์ แล้ว ไปยัง thank
    -ถ้าเกิดข้อผิดพลาดไปยังหน้า contact_form.html ใหม่


ตัวอย่างของ views.py กับ contact_form.html จะมีลักษณะดังนี้


views.py



def contact(request):
    errors = []
    if request.method == 'POST':
        if not request.POST.get('subject', ''):
            errors.append('Enter a subject.')
        if not request.POST.get('message', ''):
            errors.append('Enter a message.')
        if request.POST.get('e-mail') and '@' not in request.POST['e-mail']:
            errors.append('Enter a valid e-mail address.')
        if not errors:
            send_mail(
                request.POST['subject'],




            



                request.POST['message'],

                request.POST.get('e-mail', 'noreply@example.com'),
                ['siteowner@example.com'],
            )
            return HttpResponseRedirect('/contact/thanks/')
    return render_to_response('contact_form.html', {
        'errors': errors,
        'subject': request.POST.get('subject', ''),
        'message': request.POST.get('message', ''),
        'e-mail': request.POST.get('e-mail', ''),
    })

contact_form.html

<html>
<head>
<title>Contact us</title>
</head>
<body>
<h1>Contact us</h1>
{% if errors %}
<ul>
{% for error in errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
<form action="/contact/" method="post">
<p>Subject: <input type="text" name="subject" value="{{ subject }}"></p>
<p>Your e-mail (optional):
<input type="text" name="e-mail" value="{{ e-mail }}">

</p>
<p>Message:
<textarea name="message" rows="10" cols="50">
**{{ message }}**
</textarea>
</p>
<input type="submit" value="Submit">
</form>
</body>
</html>






พบว่าในกรณีที่มีหลายๆ field แล้วมีการ validate ด้วยการสร้าง form และ view จะยุ่งยากมาก Django มี library ที่ชื่อ django.forms ที่ช่วยเราจัดการเรื่อง form ได้


Django Form

การสร้าง form ของ Django (จะยกตัวอย่างจาก contact form ข้างต้น)
1. กำหนด form ขึ้นมา ใน form.py (จริงๆ เขียนใส่ใน views.py ไปเลยก็ได้)

from django import forms


class ContactForm(forms.Form):
    subject = forms.CharField()
    e-mail = forms.EmailField(required=False)
    message = forms.CharField()


2.เปลี่ยน contact view ใหม่โดยใช้ Django form แทนที่ requst.POST


from django.shortcuts import render_to_response
from mysite.contact.forms import ContactForm


def contact(request):
    if request.method == 'POST':
        form = ContactForm(request.POST)
    if form.is_valid():
        cd = form.cleaned_data
            send_mail(
            cd['subject'],
            cd['message'],
            cd.get('e-mail', 'noreply@example.com'),
            ['siteowner@example.com'],
        )
        return HttpResponseRedirect('/contact/thanks/')
    else:
        form = ContactForm()
    return render_to_response('contact_form.html', {'form': form})


3. สร้าง contact_form.html


<html>
<head>
<title>Contact us</title>
</head>
<body>
<h1>Contact us</h1>

{% if form.errors %}
<p style="color: red;">
Please correct the error{{ form.errors|pluralize }} below.
</p>
{% endif %}
<form action="" method="post">
<table>
{{ form.as_table }}
</table>
<input type="submit" value="Submit">
</form>
</body>
</html>




นอกจากนี้ยังมีวิธีการปรับแต่ง form อื่นๆ อีกเช่น

1. กำหนดวิธีการแสดงผลของ field
2. ตั้งค่า maximum
3. กำหนด label
4. การเพิ่ม custom validation 



from django import forms


class ContactForm(forms.Form):
    subject = forms.CharField(max_length=100)
    e-mail = forms.EmailField(required=False, label='Your e-mail address')
    message = forms.CharField(widget=forms.Textarea)


    def clean_message(self):
        message = self.cleaned_data['message']
        num_words = len(message.split())
        if num_words &lt; 4:
            raise forms.ValidationError("Not enough words!")
        return message



5. การตั้งค่า initial ให้กับ form

form = ContactForm(
    initial={'subject': 'I love your site!'}
)
return render_to_response('contact_form.html', {'form': form})





Learning Django: Django Admin Site

นอกจากการสร้าง web page แล้ว ใน web site ส่วนใหญ่จำเป็นต้องสร้าง interface สำหรับ admin ด้วย ซึ่งด้วยทั่วไปแล้ว interface มักมีหน้าตาคล้ายๆ กัน ดังนั้น Django ได้มี module ส่วนนี้มาให้ อยู่ใน django.contrib package

Activating the Admin Interface

เริ่มจากการแก้ไข settings.py ดังต่อไปนี้
1. เพิ่ม django.contrib.admin ไปในตัวแปร INSTALLED_APPS
2. เช็คดูว่า INSTALLED_APPS มี app เหล่านี้อยู่ (ปกติมีมาให้แล้ว)
- django.contrib.auth
- django.contrib.contenttypes
- django.contrib.sessions
3. เช็คดูว่า MIDDLEWARE_CLASSES มี class เหล่านี้อยู่

    'django.middleware.common.CommonMiddleware'
    'django.contrib.sessions.middleware.SessionMiddleware'
    'django.contrib.auth.middleware.AuthenticationMiddleware'

หลังจากนั้น sync database (pythong manage.py syncdb) ในขั้นตอนนี้ ระบบจะถามถึง super user name และ password สำหรับ web site ให้ตั้งค่าไป


ขั้นต่อไปให้ทำการแก้ไข map ใน urls.py โดยการ uncomment บรรทัดเหล่านี้ออก


# from django.contrib import admin
# admin.autodiscover()

# (r'^admin/', include(admin.site.urls)),


เท่านี้เราก็จะได้ admin site ที่สามารถจัดการ user และข้อมูลต่างๆ (ลองเปิดดูด้วย http://127.0.0.1:8000/admin/)

ทีนี้เราจะเพิ่ม models ของเราเข้าไปใน admin site เพื่อให้สามารถ เพิ่ม, ลบ, แก้ไข database ได้ โดยทำตามขั้นตอนดังนี้
1. ใน folder app (ภายใน project folder ในที่นี้คือ mysite/books) สร้าง ไฟล์ชื่อ admin.py เนื้อหาดังต่อไปนี้

from django.contrib import admin
from mysite.books.models import Publisher, Author, Book
admin.site.register(Publisher)
admin.site.register(Author)
admin.site.register(Book)


About Model in Admin Site

การจัดการ models ใน Admin Site จากตัวอย่าง app books เราสามารถเพิ่ม, ลบ ข้อมูลได้ แต่อาจจะมีปัญหาจุกจิก เล็กน้อยเช่น การเพิ่ม record จะต้องเติมข้อมูลทุกช่องลงไป (เนื่องจากตอนสร้าง ไม่ได้กำหนดว่าสามารถ null ได้ เป็นต้น) ในส่วนนี้จะทำการสรุป วิธีการปรับแต่งข้อมูล เล็กๆ น้อยๆ เพื่อที่จะสามารถ edit database ได้ใน Admin Site

1. Make Fields Optional


class Author(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=40)
    email = models.EmailField(blank=True)



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)



2. Customizing Fields Labels กำหนดชื่อ field ให้สื่อความหมายมากขึ้น


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')


Model Admin Class

การแก้ไขการแสดงผล database ในส่วนที่กล่าวมานั้นเป็นการ แก้ไขที่ model level ถ้าจะแก้ไขที่ admin level เราสามารถใช้ ModelAdmin class มาช่วยกำหนดการแสดงผลได้

วิธีการใช้ ModelAdmin class ใน admin.py สามารถสรุปได้ดังนี้
1. สร้าง class โดย inherit มากจาก admin.ModelAdmin
2. กำหนด customization ที่ต้องการ
3. register model โดยมี class ใหม่นี้เป็น พารามิเตอร์


ลองดูตัวอย่างสิ่งที่เรา customize ใน admin.py

1.ปรับlist display สำหรับ author, book, publisher
2.เพิ่ม search bar สำหรับ author
3.เพิ่ม date filter ให้ book
4.เรียงลำดับ date สำหรับ book
5.กำหนดและเรียงลำดับของ field

from django.contrib import admin
from mysite.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',)
    ordering = ('-publication_date',)

    fields = ('title', 'authors', 'publisher')


admin.site.register(Publisher)
admin.site.register(Author, AuthorAdmin)
admin.site.register(Book, BookAdmin)

Learning Django: Data access

หลังจากที่เรา sync database แล้วเราก็สามารถจัดการ database ได้ ในตอนนี้เราจะยกตัวอย่างวิธีการจัดการ database ผ่านทาง shell python ของ Django

เริ่มต้นโดยใช้คำสั่ง

python manage.py shell

เป็นการเรียก python shell โดยใช้ environment ของ project นี้ (mysite)

ลองดูคำสั่งเหล่านี้


>>> 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
[, ]

เป็นการสร้าง object แบบ Publisher สองตัว (p1,p2) โดยแล้วใส่ลงใน database โดย method ที่ชื่อ save
ถ้าเราใส่ข้อมูลลงใน database เลยเราสามารถใช้คำสั่ง ต่อไปนี้แทนได้


>>> p1 = Publisher.objects.create(name='Apress',
... address='2855 Telegraph Avenue',
... city='Berkeley', state_province='CA', country='U.S.A.',
... website='http://www.apress.com/')
>>> p2 = Publisher.objects.create(name="O'Reilly",
... address='10 Fawcett St.', city='Cambridge',
... state_province='MA', country='U.S.A.',
... website='http://www.oreilly.com/')

สังเกตว่า publisher_list แสดงค่าออกมาเป็น [, ] ซึ่งอ่านเข้าใจลำบาก เราจะแก้ไข method __unicode__(self) ของ model ต่างๆ เพื่อให้อ่านเข้าใจง่ายขึ้น (คล้ายกับการ override function toString())

ผลจากการแก้ไข 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()
    
    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

หลังจากแก้ไขแล้วเราลองมาดูความเปลี่ยนแปลง(ออกจาก shell แล้วเข้าใหม่)


>>> from books.models import Publisher
>>> publisher_list = Publisher.objects.all()
>>> publisher_list
[, ]


ลองมาดู database operation เบื้องต้น ใน Django
1. การ insert และ update data
- สร้าง record

>>> p = Publisher(name='Apress',
... address='2855 Telegraph Ave.',
... city='Berkeley',
... state_province='CA',
... country='U.S.A.',
... website='http://www.apress.com/')
- insert record
>>> p.save()
- change record
>>> p.name = 'Apress Publishing'
- update record
>>> p.save()

2. select record
- select all

>>> Publisher.objects.all()
[, ]

- select with where clause

>>> Publisher.objects.filter(name='Apress')
[]


>>> Publisher.objects.filter(country="U.S.A.", state_province="CA")
[]


>>> Publisher.objects.filter(name__contains="press")
[]

3. select single record

>>> Publisher.objects.get(name="Apress")


4. select with order

>>> Publisher.objects.order_by("name")
[, ]


>>> Publisher.objects.order_by("state_province", "address")
[, ]


>>> Publisher.objects.order_by("-name")
[, ]

5. select with where and order

>>> Publisher.objects.filter(country="U.S.A.").order_by("-name")
[, ]

6. select with limit

>>> Publisher.objects.order_by('name')[0]


>>> Publisher.objects.order_by('name')[0:2]

7. update record
>>> Publisher.objects.filter(id=52).update(name='Apress Publishing')

>>> Publisher.objects.all().update(country='USA')

8. remove record

>>> p = Publisher.objects.get(name="O'Reilly")
>>> p.delete()
>>> Publisher.objects.all()
[]

Learning Django: Create Model and Django App

ในขั้นแรก เราจะสร้าง app ใหม่ใน project ขึ้นมาก่อน เนื่องจากใน Django ถ้าจะสร้าง models (database layers ของ Django) จะต้องสร้าง Django app ขึ้นมา เพราะ models จะต้องอยู่ใน app

Create Django App

เราสามารถสร้าง Django App โดยใช้คึำสั่ง

python manage.py startapp app_name


ในตัวอย่างเราจะสร้าง app ที่ชื่อ books => python manage.py startapp books

Django จะสร้าง folder app_name พร้อมไฟล์อีก 4 ไฟล์
1. __init__.py
2. models.py
3. tests.py
4. views.py

Create Model

การสร้าง model นั้นเราสามารถสร้างโดยการแก้ไข models.py ใน app folder ลองดูตัวอย่างของ model


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()


เป็นการสร้าง model ขึ้นมา 3 ตัว (เหมือนกับการกำหนด table ใน database ต่างกันตรงที่ใช้ไวยกรณ์ของ python)


Installing Model

หลังจากที่เราสร้าง Model (3 ตัว) เราจะทำการติดตั้ง model นี้ เนื่องจาก model ต้องอยุ่ใน app (book) เราจะทำการติดตั้ง books ไปใน project เรา โดยการแก้ไขตัวแปร INSTALLED_APPS ในไฟล์ settings.py


INSTALLED_APPS = (
    # 'django.contrib.auth',
    # 'django.contrib.contenttypes',
    # 'django.contrib.sessions',
    # 'django.contrib.sites',
     'mysite.books',
)

หลังจากนั้นให้สร้าง table ตาม model นี้ใน database ตัว Django เอง มี utility ช่วยโดยใช้คำสั่ง syncdb

python manage.py syncdb

คำสั่งนี้จะช่วย sync ตัว model ที่เรามีอยู่ใหัตรงกับ database

ต่อไปเราจะมารู้จักกับวิธี access data กัน

Learning Django: Configuring Database


Configuring the Database


สิ่งที่เป็นจุดเด่นของ Django คือการ สร้าง Database driven application ได้ง่าย โดยอาศัย framework แบบ MTV (คล้ายๆ MVC) ทั้งนี้เนื่องจากพื้นฐานของ Django เป็น python ดังนั้นเราสามารถใช้คำสั่ง sql ในการติดต่อกับ database ได้ โดยอาศัย template, กับ view ดูตัวอย่าง code


from django.shortcuts import render_to_response
import MySQLdb

def book_list(request):
    db = MySQLdb.connect(user='me', db='mydb', passwd='secret', host='localhost')
    cursor = db.cursor()
    cursor.execute('SELECT name FROM books ORDER BY name')
    names = [row[0] for row in cursor.fetchall()]
    db.close()
    return render_to_response('book_list.html', {'names': names})

แน่นอนว่า Django วิธีที่จะจัดการส่วนที่ซ้ำซ้อนพวกนี้ (เช่นการสร้าง query, การเปิดปิด connection)
เรามาเริ่มต้นที่การ config database



เพื่อความง่ายในบทความนี้จะใช้ database engine SQLite3 ที่มากับตัว python 2.5+ ดังนั้น หลังจากนั้นแก้ค่าตัวแปร  DATABASE ที่อยู่ใน settings.py ดังนี้

- ENGINE = 'django.db.backends.sqlite3'
- NAME = ตั้งค่าเป็น full path file ที่เราจะใช้เก็บฐานข้อมูล

นอกนั้นไม่ต้องตั้งค่า(สำหรับ SQLite3)

Learning Django: Template

จากตอนที่แล้วจะเห็นว่าการสร้าง view ขึ้นมายังจะต้องยุ่งยากในการ print html tag ขึ้นมาอีกซึ่งไม่ต่างกับ PHP เท่าไร ใน Django เราแก้ปัญหานี้โดยใช้ template

Template

ใน Django เราสามารถสร้าง template สำหรับแสดงผล (presentation) ให้แยกกับส่วน logic ลองมาดู concept ของ template กันอย่างกระชับ

เริ่มจากการเปิด python prompt แล้ว ลอง code ต่อไปนี้


>>> 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.

ลองมาดู code กัน
1. import template เข้ามา
2. สร้าง template ชื่อ t
3. สร้าง context  c ขึ้นมา โดยใน context นี้มีค่า name=Andrian
4. ให้ template t แสดงผลโดยอ้างอิง context c จะได้ผลลัพธ์ออกมา
5. เปลี่ยนค่า context c โดยให้ name=Fred
6. ให้ template t แสดงผลโดยอ้างอิง context c จะได้ผลลัพธ์ออกมา เนื่องจาก context c เปลี่ยนค่าไป ผลจึงออกมาไม่เหมือนเดิม

เรานำ template มาประยุกต์ใช้กับ view ได้หลายวิธี แต่วิธีแนะนำเพื่อที่จะแยก ระหว่าง presentation กับ logic ขั้นตอนมีดังนี้

1. กำหนด template directory ใน settings.py โดย TEMPLATE_DIRS ในที่นี้จะสร้าง folder ที่ชื่อ templates ใน folder mysite


import os.path
....................
TEMPLATE_DIRS = (
    os.path.join(os.path.dirname(__file__), 'templates').replace('\\','/'),
)

2. เพิ่ม code ส่วนนี้ไปใน views.py



from django.template.loader import get_template
from django.template import Context
from django.http import HttpResponse
import datetime


def current_datetime(request):
    now = datetime.datetime.now()
    t = get_template('current_datetime.html')
    html = t.render(Context({'current_date': now}))
    return HttpResponse(html)

หรือเราจะใช้ feature ที่ชื่อ shortcut ใน Django เพื่อประหยัดการเขียน code

from django.shortcuts import render_to_response


import datetime


def current_datetime(request):
    now = datetime.datetime.now()
    return render_to_response('current_datetime.html', {'current_date': now})


โดย current_datetime.html จะเป็น html ไฟล์ที่มี Tag (คล้ายๆ PHP) โดยส่งค่า context ไปให้(ในกรณีนี้ current_date เป็น object ประเภท datetime)


Template Tag

ในส่วนนี้เราจะสรุป Template Tag คร่าวๆ

1. Tag ใน template จะอยู่ในเครื่องหมายปีกกา {} (คล้ายๆ PHP อยู่ระหว่า )
2. การอ้างอิงถึง variable ทำได้โดย ใช้ {{ variable_name }}
3. มี control ต่างๆ ดังนี้
    - {% if %}, {% else %}, {% endif %}
    - {% for %}, {% endfor %}
    - {% ifequal %},{% ifnotequal %}, {% endifequal %}, {% endifnotequal %}
4. comment 
    - บรรทัดเดียวใช้ {# #}
    - หลายบรรทัดใช้ {% comment %}, {% endcomment %}
5. สามารถใช้ filter ได้
    - {{ name|lower }} เป็นการเปลี่ยนค่า name ให้เป็น lower case
    - filter สามารถ pipe ได้ {{ my_list|first|upper }} เป็นการดึงค่าแรกใน my_list ออกมาแล้วเปลี่ยนเป็น upper case


Learning Django: Create Views

Creaet Views

Django ใช้การพัฒนาในแบบ MTV คือ Model, Template, และ View ในส่วนนี้เราจะมาดูเรื่อง View กัน

เริ่มต้นจากการสร้างไฟล์ที่ชื่อ

views.py


from django.http import HttpResponse
def hello(request):
return HttpResponse("Hello world")


เป็นไฟล์ python ทีมี module เดียวชื่อ hello ซึ่งจะถือเป็น view อันหนึ่ง ลองรัน web server (python manage.py runserver) ดูก็จะไม่เห็นการเปลี่ยนแปลงใดๆ เนื่องจากยังไม่ได้มีการ map view ที่ชื่อ hello นี้เข้ากับ pattern ใดๆ ซึ่งคงเดาใด้ว่า การ map นี้เรากำหนดไว้ในไฟล์ urls.py

ลองดูเนื้อหาในไฟล์ urls.py ที่ Django สร้างขึ้นมาให้ (ตัวอย่างนี้ลบ comment ออกแล้ว)


from django.conf.urls.defaults import *


urlpatterns = patterns('',
)

ในส่วนนี้จะเป็นการกำหนดการ map ระหว่าง pattern กับ view จะเห็นว่าเรายังไม่มีการ map ใดๆ (พารามิเตอร์ตัวแรกไม่ได้อ้างถึงการ map) ดังนั้น ไม่ว่าเราจะ browse ไปที่ใดใน http://127.0.0.1:8000/ ก็ยังจะขึ้นหน้าเหมือนเดิม (ไม่มี error 404)

ทีนี้เราจะ map view hello เข้ากับ url http://127.0.0.1:8000/hello/ โดยการแก้ไข urls.py ตามขั้นตอนดังนี้
1. import module hello โดยใช้คำสั่ง from mysite.views import hello
2. เพิ่ม map ระหว่าง view hello กับ pattern /hello/ โดยเพิ่ม  ('^hello/$', hello) เข้าไปใน urlpatterns
(พารามิเตอร์แรกเป็น pattern เป็น regular exprssion โดย '^' หมายถึงจุดเริ่่ม pattern '$' หมายถึงจุดสิ้นสุด ถ้าเรากำหนดเป็น 'hello' ธรรมดา มันจะไปตรงกับ path อื่นเช่น http://127.0.0.1:8000/hello/test/ เป็นต้น ส่วนพารามิเตอร์ที่สองเป็นชื่อ view ที่กำหนดไว้ใน module)

ไฟล์ที่แก้ไขแล้วจะมีลักษณะดังนี้


from django.conf.urls.defaults import *
from mysite.views import hello


urlpatterns = patterns('',
    ('^hello/$', hello),
)
*หลัง  ('^hello/$', hello) ต้องมี  "," ด้วย

เมื่อลองทดสอบ run server ดู จะสามารถ browse view ที่ชื่อ hello โดยผ่าน url http://127.0.0.1:8000/hello/
แล้วถ้าไปยัง path อื่นคราวนี้จะเกิด error 404 ขึ้น

เราสามารถสร้าง view แบบไดนามิกได้ ลองดูตัวอย่าง code ที่เพิ่มขึ้นใน views.py

from django.http import HttpResponse
import datetime

def hello(request):
    return HttpResponse("Hello world")

def current_datetime(request):
    now = datetime.datetime.now()
    html = "It is now %s." % now
    return HttpResponse(html)

แลัวแก้ไข urlpatterns เป็น

urlpatterns = patterns('',
    ('^hello/$', hello),
    ('^time/$', current_datetime),
)


เป็นการเพิ่ม view ขื่อ current_datetime ขึ้นมาอีก โดย view นี้ไม่ใช่ view แบบ static มีการเปลี่ยนแปลงเนื้อหาทุกครั้ง


Dynamic URL

ทีนี้เราจะมาลอง map dynamic URL เริ่มต้นที่ การแก้ไข urlpatterns

urlpatterns = patterns('',
    (r'^hello/$', hello),
    (r'^time/$', current_datetime),
    (r'^time/plus/(\d{1,2})/$', hours_ahead),
)

เราได้สร้าง map สำหรับ pattern time/plus/(\d{1,2}) (ถ้าไม่เข้าใจลองหาอ่านเรื่อง regular expression) ซึ่งทำให้สามารถส่งผ่านค่าในวงเล็บไปให้กับ view ได้เสมือนเป็น parameter ใน view 

สังเกตว่าเราใช้ r นำหน้า pattern เพื่อไม่ให้ python ทำการประมวลผล escape sequence

โคดสำหรั้บ hours_ahead view

from django.http import Http404, HttpResponse
import datetime

def hours_ahead(request, offset):
    try:
        offset = int(offset)
    except ValueError:
        raise Http404()
    dt = datetime.datetime.now() + datetime.timedelta(hours=offset)
    html = "In %s hour(s), it will be %s." % (offset, dt)
    return HttpResponse(html)











Learning Django: Create Website

Create Website

ขั้นแรกก่อนจะสร้าง web page ก็ต้องสร้าง website กันก่อน ลองมาสร้าง website โดยใช้ชื่อ project ว่า mysite
การสร้างมีขั้นตอนดังนี้
1. ไปยัง folder ที่จะสร้าง project
2. รัน
django-admin.py startproject mysite 
(ใน windows อาจจะมีปัญหาเรื่อง path ในการเรียก file django-admin.py จะอยู่ใต้ folder scripts ใน python directory)
3. เราจะได้ folder ที่ชื่อ mysite ภายในประกอบด้วย file ประเภท .py ทั้งหมด 4 files
    1. __init__.py ไฟล์สำหรับจัดการ package ของ python
    2. manage.py ไฟล์ utilites สำหรับจัดการ Django project นั้นๆ
    3. settings.py ไฟล์ตั้งค่าสำหรับ Django project
    4. urls.py เอาไว้ map ระหว่าง url และ module ต่างๆ

Running Application

หลังการสร้าง website แล้วก็เตรียมพร้อมจะสร้าง page แต่ก่อนอื่น มาดูวิธีการ run project ก่อน

ในตัว Django เองจะมี web server มาให้แล้วสามารถใช้ทดสอบในระหว่างการพัฒนาก่อนที่จะ deploy ลง server ของจริง เราสามารถ startup web server โดยใช้คำสั่ง

python manage.py runserver

(manage.py ที่อยู่ใน folder mysite)

หลังจากนั้นจะสามารถ view page ได้โดยผ่านทาง http://127.0.0.1:8000/

เราสามารถเปลี่ยน port และ ip ของ web server ได้

Learning Django: Install

ความต้องการพื้นฐานและสิ่งที่ต้อง download

การจะใช้งาน Django จะต้องติดตั้ง component ต่างๆ ดังต่อไปนี้
1. python เนื่องจาก Django ใช้ภาษา python ดังนั้นจะต้องมี python ในระบบ หาโหลดจาก http://www.python.org/download/ เนื่องจากขณะนี้ Django ไม่ support python 3.x ให้ติดตั้งเวอร์ชัน 2.x แทน ซึ่งจริงๆ ควรจะเป็น 2.5 ขึ้นไป
2. Django แน่นอนต้องมี โหลดได้จาก http://www.djangoproject.com/download/
3. Database engine ไม่จำเป็นต้องมี (แต่ถ้าไม่ใช้ แนะนำให้พัฒนาโดยใช้ php จะง่ายกว่า 555) ในตัว Django เองรองรับ อยู่ 4 ตัวคือ

- PostgreSQL
- SQLite3
- MySQL
- Oracle
ถ้าจะลองใช้ดูก่อนสามารถใช้ SQLite3 ซึ่งมีมาให้แล้วใน python 2.5 เลยไม่ต้องติดตั้้งเพิ่ม


วิธีการติดตั้ง(สำหรับ windows)

1. ติดตั้ง python (เป็น .msi)
2. แตกไฟล์ Django ใส่ใน folder ที่ต้องการ
3. เปิด command prompt ใน mode admin
4. รันคำสั่ง setup.py install ที่ folder จากข้อสอง ซึ่งในขึ้นตอนนี้ ถ้าไม่ได้ associate file ประเภท py ไว้ก็ให้
ระบุเอง
5. ลองตรวจสอบ การติดตั้ง Django โดยเข้าไปใน python prompt ใส่คำสั่ง import django แล้วตามด้วย django.VERSION ตามลำดับ ถ้าไม่เกิด error แสดงว่าการติดตั้งเรียบร้อย
6. ติดตั้ง database engine เพิ่ม (ในกรณีนี้เราใช้ SQLite3 จึงไม่ต้องติดตั้งเพิ่ม)
7. ติดตั้ง IDE เพิ่มถ้าต้องการ (แนะนำ aptana studio3 แต่ตอนนี้ยังเป็น beta อยู่) ใน blog นี้จะใช้ notepad

เป็นอันเสร็จสิ้นการติดตั้ง Django พร้อมใช้งาน

Create website using Django

มีงานที่ต้องเขียน web app อีกแล้ว เลยลองนั่ง search หา web application framework มาดู เนื่องจาก ASP.NET กับ Flex ที่ใช้อยู่ไม่น่าจะเวิร์ค เขียน PHP ก็ยุ่งยากอีก  มาสะดุด Django ตรงที่มันเขียนว่า "The Web framework for perfectionists with deadlines" โดนใจมากๆ เลยลองหาหนังสืออ่านแล้วสรุป ตามความเข้าใจแบบคร่าวๆ สุดขีด ใครสนใจเนื้อหาเต็มๆ ของที่แปลมาลองดูได้จากหนังสือ The Definitive Guide
to Django Web Development Done Right, Second Edition ของ Apress