วันศุกร์ที่ 6 ธันวาคม พ.ศ. 2556

Django documentation First steps Tutorial: Part 3

Writing your first Django app, part 3
Tutorial part 3 ก็จะทำต่อมาจาก Tutorial part 2 แต่เราจะสนใจในเรื่องการสร้าง public interface – “views.”

 Write your first view
เริ่มจากเข้าไปแก้ไขไฟล์ polls/views.py จากนั้นพิมพ์โค้ดตามนี้
 from django.http import HttpResponse  
   
 def index(request):  
   return HttpResponse("Hello, world. You're at the poll index.")  
สร้างไฟล์ขึ้นมาชื่อ urls.py ใน Directory polls/
 polls/  
   __init__.py  
   admin.py  
   models.py  
   tests.py  
   urls.py  
   views.py  
ทำการแก้ไขโค้ดใน polls/urls.py ตามดังนี้
 from django.conf.urls import patterns, url  
   
 from polls import views  
   
 urlpatterns = patterns('',  
   url(r'^$', views.index, name='index')  
 )  
ขั้นตอนต่อไปก็ให้เข้าไปแก้ไข ใน [Django projectname]/urls.py ในที่นี้ชื่อ DjangoTutorial
 from django.conf.urls import patterns, include, url  
   
 from django.contrib import admin  
 admin.autodiscover()  
   
 urlpatterns = patterns('',  
   url(r'^polls/', include('polls.urls')),  
   url(r'^admin/', include(admin.site.urls)),  
 )  
จากทำการทดสอบโดยทดลองเข้าที่ URL http://127.0.0.1:8000/polls/ ต้องทำการ run server เหมือน Toturial ที่ผ่านมาก่อนหน้า ถ้าไม่มีอะไรผิดพลาด brower ก็จะแสดงข้อความดังรูป


หลักการทำงาน
เมื่อเปิด browser เข้าไปที่ URL  http://127.0.0.1:8000/polls/ Django จะตรวจสอบ urlpatterns ที่ DjangoTutorial/urls.py จากนั้นทำการส่งต่อไปให้ polls/urls.py โดยตัด URL ส่วนหน้าออก จากนั้นก็จะตรวจสอบ urlpatterns เช่นเดิมและตรงกับ r'^$' ส่งต่อไปยัง views.index ใน function index จะรีเทิร์นแสดงข้อความออกมาแสดงที่ browser

 Writing more views
ทดสอบ Django ด้วยการเพิ่ม urlpatterns และ function ที่รีเทิร์นแสดงข้อความแบบต่างๆ จาก URL ที่ต่างกัน มีการใช้ Regular Expressions ในการกำหนดการรับข้อมูล เพื่อส่งให้ function 
ทำการแก้ไขโค้ดตามดังต่อไปนี
polls/views.py
 def detail(request, poll_id):  
   return HttpResponse("You're looking at poll %s." % poll_id)  

 def results(request, poll_id):  
   return HttpResponse("You're looking at the results of poll %s." % poll_id)  

 def vote(request, poll_id):  
   return HttpResponse("You're voting on poll %s." % poll_id)  

polls/urls.py
 from django.conf.urls import patterns, url  
   
 from polls import views  
   
 urlpatterns = patterns('',  
   # ex: /polls/  
   url(r'^$', views.index, name='index'),  
   # ex: /polls/5/  
   url(r'^(?P<poll_id>\d+)/$', views.detail, name='detail'),  
   # ex: /polls/5/results/  
   url(r'^(?P<poll_id>\d+)/results/$', views.results, name='results'),  
   # ex: /polls/5/vote/  
   url(r'^(?P<poll_id>\d+)/vote/$', views.vote, name='vote'),  
 )  

แสดงหน้าจอ browser ที่ URL ต่างๆ
urlpatterns: r'^(?P<poll_id>\d+)/
urlpatterns: r'^(?P<poll_id>\d+)/results/
urlpatterns: r'^(?P<poll_id>\d+)/vote/


Write views that actually do something
เป็นการนำข้อมูลใน database ออกมาแสดงในหน้า index(127.0.0.1:8000) function index จะรีเทิร์น object ของ class Poll 5 อันดับแรกจากการเรียงโดยใช้ pub_date เพื่อแสดง question ของแต่ละ object ให้ทดลองแก้ไขโค้ดตามนี้
 polls/views.py
 from django.http import HttpResponse  
   
 from polls.models import Poll  
   
 def index(request):  
   latest_poll_list = Poll.objects.order_by('-pub_date')[:5]  
   output = ', '.join([p.question for p in latest_poll_list])  
   return HttpResponse(output)  
เมื่อลองดูใน browser
ทดลองแก้ไขโดยให้แสดงเฉพาะอันดับแรก 
 latest_poll_list = Poll.objects.order_by('-pub_date')[:1]   
Show first order [:1]
ทดลองแก้ไขโดยให้จัดเรียงจาก question  **เครื่องหมาย(-) เรียงจากมากไปน้อย
 latest_poll_list = Poll.objects.order_by('-question')[:5]  
ทดลองแก้ไขจากการแสดง output จาก question เป็น pub_date ของ object 
 output = ', '.join([str(p.pub_date) for p in latest_poll_list])  
Using the Template System
Template คือ แบบหรือโครงสร้างของเวป โดยจะแยกส่วนโค้ดกับส่วนหน้าเวปออกจากกัน ทำให้สะดวกต่อการใช้งานมากขึ้น เพราะทำให้หน้าเวปเป็นแบบ  dynamic ข้อมูลที่ต้องการนำมาแสดงผล จะถูกนำมา mapping template variable
ขั้นแรกต้องทำการเซ็ท TEMPLATE_DIRS ใน [Django projectname]/settings.py ให้เซ็ท path มาที่โฟลเดอร์ polls/templates สามารถใช้ Command ~$ pwd ในการดูที่อยู่ของ directory
ส่วนที่ทำสีจางให้ใส่ที่อยู่ของ directory ของคุณเอง
 TEMPLATE_DIRS = ([os.path.join(BASE_DIR, 'templates')],  
   '/home/nazari/Desktop/work/w4-2/DjangoTutorial/polls/templates',  
 )  
ต่อมาให้ทำการสร้างไฟล์และโฟลเดอร์ polls/templates/polls/index.html โดยสร้างอยู่ในโฟลเดอร์ templates ที่ได้สร้างขึ้นมาในขั้นแรก จากนั้นก็พิมพ์โค้ดด้านล่างใส่เข้าไป
index.html
 {% if latest_poll_list %}  
   <ul>  
   {% for poll in latest_poll_list %}  
     <li><a href="/polls/{{ poll.id }}/">{{ poll.question }}</a></li>  
   {% endfor %}  
   </ul>  
 {% else %}  
   <p>No polls are available.</p>  
 {% endif %}  
ทำการแก้ไข function index() ใน views.py และ import Poll จาก models.py
 polls/views.py
 from django.http import HttpResponse  
 from django.template import RequestContext, loader  
   
 from polls.models import Poll  
   
 def index(request):  
   latest_poll_list = Poll.objects.order_by('-pub_date')[:5]  
   template = loader.get_template('polls/index.html')  
   context = RequestContext(request, {  
     'latest_poll_list': latest_poll_list,  
   })  
   return HttpResponse(template.render(context))  
จากโค๊ดที่เพิ่มมา ตัวแปร template จะทำการโหลด polls/index.html มาเก็บไว้ ตัวแปร context จะเป็นการ mapping template variable กับ ตัวแปร latest_poll_list 
Show list poll and link to poll detail

Detail poll What's time?

Detail poll What's up?

A shortcut: render()
จากรูปแบบการใช้ template ด้านบนเป็นรูปแบบส่วนมากที่ใช้ในการ โหลด template และรีเทิร์น HttpResponse ของผลลัพธ์ ของ template ดังนั้น Django จึงมีการสร้าง shortcut เพื่อให้สะดวกต่อการใช้งาน ดังโค้ดด้านล่าง และให้ผลลัพธ์ที่เหมือนกัน
 polls/views.py
 from django.shortcuts import render  
   
 from polls.models import Poll  
   
 def index(request):  
   latest_poll_list = Poll.objects.all().order_by('-pub_date')[:5]  
   context = {'latest_poll_list': latest_poll_list}  
   return render(request, 'polls/index.html', context)  

Raising a 404 error
เริ่มจากสร้างไฟล์ polls/detail.html ใช้แสดงรายละเอียดของแต่ละ poll
detail.html 
 <h1>{{ poll.question }}</h1>  
 <ul>  
 {% for choice in poll.choice_set.all %}  
   <li>{{ choice.choice_text }}</li>  
 {% endfor %}  
 </ul>  
ต่อไปแก้ไขไฟล์ใน polls/views.py โดยพิมพ์ตามโค้ดด้านล่าง
 polls/views.py
 from django.http import Http404  
 from django.shortcuts import render  
   
 from polls.models import Poll  
 # ...  
 def detail(request, poll_id):  
   try:  
     poll = Poll.objects.get(pk=poll_id)  
   except Poll.DoesNotExist:  
     raise Http404  
   return render(request, 'polls/detail.html', {'poll': poll})  
ผลลัพธ์ที่ได้จาก browser
page detail จะแสดงแต่ละ choice ใน poll
 ทดสอบเข้า http://127.0.0.1:8000/polls/3/ จะขึ้น Http404 เพราะ poll มีเพียง 2 object


A shortcut: get_object_or_404()
เช่นเดียวกันกับ render() Django ได้สร้าง shortcut ของ Http404 เพื่อให้สะดวกต่อการใช้งาน โดยแก้ไขตามโค้ดนี้
 polls/views.py
 from django.shortcuts import render, get_object_or_404  
   
 from polls.models import Poll  
 # ...  
 def detail(request, poll_id):  
   poll = get_object_or_404(Poll, pk=poll_id)  
   return render(request, 'polls/detail.html', {'poll': poll})  


Removing hardcoded URLs in templates
จะพบว่าการระบุ URL เพื่อเชื่อมลิงค์ต่อไปยังส่วนอื่นแบบเดิมนั้นมีความยากในการใช้งานเพราะต้อง กำหนด URL ใน index.html เมื่อจะทำการแก้ไข urlpatterns จะต้องเข้ามาแก้ไขใน index.html ด้วย
polls/index.html
 <li><a href="/polls/{{ poll.id }}/">{{ poll.question }}</a></li>  
แก้ไขเป็น
 <li><a href="{% url 'detail' poll.id %}">{{ poll.question }}</a></li>  
และเพิ่ม urlpatterns ใน polls/urls.py
polls/urls.py
 ...  
 # the 'name' value as called by the {% url %} template tag  
 url(r'^(?P<poll_id>\d+)/$', views.detail, name='detail'),  
 ...  
 ...  
 # added the word 'specifics'  
 url(r'^specifics/(?P<poll_id>\d+)/$', views.detail, name='detail'),  
 ...  
เมื่อคลิกจากหน้า index สังเกตุที่ URLจะเป็น http://127.0.0.1:8000/polls/specifics/2/

จากการทดสอบ กำหนดให้้ urlpattern ต่างกันแต่เรียกใช้ function detail เหมือนกัน พบว่าจะเลือกจาก urlpatterns ที่อยู่จากล่างก่อน คือ จะไล่ลำดับจากล่างขึ้นบน

Namespacing URL names
ในตัวอย่างที่เราได้ทำมีเพียงแค่แอป polls แต่ใน Django project อาจจะมีอยู่หลาย app วิธีการที่ Django ให้ url names แตกต่างจากอื่น ๆ ยกตัวอย่างเช่น poll มี detail view ส่วนการทำให้รู้ว่า view แต่ละอันเป็นของ app อะไร ก็คือ เพิ่ม namespace ให้กับ root ของ URLconf ของคุณ
[Django projectname]/urls.py
 from django.conf.urls import patterns, include, url  
   
 from django.contrib import admin  
 admin.autodiscover()  
   
 urlpatterns = patterns('',  
   url(r'^polls/', include('polls.urls', namespace="polls")),  
   url(r'^admin/', include(admin.site.urls)),  
 )  
ตอนนี้ template ใน polls/index.html ของคุณจะเป็น
polls/index.html
 <li><a href="{% url 'detail' poll.id %}">{{ poll.question }}</a></li>  
แก้ไขเป็น
 <li><a href="{% url 'polls:detail' poll.id %}">{{ poll.question }}</a></li>  


Reference
https://docs.djangoproject.com/en/1.6/intro/tutorial03/

ไม่มีความคิดเห็น:

แสดงความคิดเห็น