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 SystemTemplate คือ แบบหรือโครงสร้างของเวป โดยจะแยกส่วนโค้ดกับส่วนหน้าเวปออกจากกัน ทำให้สะดวกต่อการใช้งานมากขึ้น เพราะทำให้หน้าเวปเป็นแบบ 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.pypolls/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 ใช้แสดงรายละเอียดของแต่ละ polldetail.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.pypolls/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/
ไม่มีความคิดเห็น:
แสดงความคิดเห็น