วันเสาร์ที่ 30 พฤศจิกายน พ.ศ. 2556

ศึกษาการใช้งาน Django tutorial part 1-4

tutorial part 1

     ใน tutorial part 1 จะพูดถึงงวิธีการสร้าง Django App อย่างง่าย รู้จักคำสั่งพื้นฐานในการสร้าง App เพื่อนำไปใช้ในการพัฒนา web application ได้

ทำไมต้องมี apps ในไฟร์ project
        project สร้างขึ้นเพื่อเก็บข้อมูลการแสดงผล และ setting ค่าต่างๆใน database เมื่อมีการแสดงผลมากขึ้น การที่มีเฉพาะไฟร์ project เพียงอย่างเดียวอาจทำให้ยุ้งยากต่อการแก้ไข
        django app จึงถูกสร้างขึ้นเพื่อความเป็นระเบียบ ง่ายต่อการแก้ไข และถูกสร้างขึ้นเพื่อใช้ในการพัฒนา web application โดยเฉพาะ


คำสั่งที่เกียวข้อง
        - เราสามารถทำการตรวจสอบ version ของ django โดยใช้คำสั่ง  

              python -c "import django; print(django.get_version())"


        - เราสามารถกำหนด port ในการ run server ได้โดยใช้คำสั่ง

                 python manage.py runserver 8080  

                 ซึ่ง server ก็จะรันอยู่ที่ port 8080

        - เราสามารถกำหนด HOST ที่จะ run server ได้โดยใช้คำสั่ง

                 python manage.py runserver 0.0.0.0:8000

                 ซึ่ง server ก็จะรันอยู่ที่ HOST: 0.0.0.0

        - การ set time zone เพื่อให้ได้เวลาของฐานข้อมูลจริง ณ ที่อยู่ปัจจุบัน เราสามารถ set โดยเข้าไปในไฟร์ settings.py ที่อยู่ใน Directory ของ project ทำการเปลี่ยนตรง TIME_ZONE = 'Asia/Bangkok'


ขั้นตอนและวิธีการสร้าง Django apps
       1. cd เข้าไปยัง part ที่ได้ทำการสร้าง project ไว้ ซึ่งเราจะสร้าง app ไว้ใน part ที่มีไฟร์ manage.py อยู่


       2. เริ่มทำการ startapp โดยใช้คำสั่ง  

               python manage.py startapp polls 


       3. เมื่อมีการใช้คำสั่ง startapp จะมีไฟร์ทั้งหมดเพิ่มขึ้นมาใน Directory polls ดังนี้



       4. ทำการจัดการเกี่ยวกับไฟร์ models.py ซึ่งเป็นไฟร์ที่ใช้ในการเก็บรูปแบบข้อมูลพื้นฐานต่างๆ เกี่ยวกับ app และ admin เช่น วัน เวลาปัจจุบัน ทำการแก้ไขไฟร์ models.py โดยการเพิ่มคลาส Choice และ Poll

              from django.db import models


            class Poll(models.Model):
                     question = models.CharField(max_length=200) 
                                   #เก็บค่า question เป็น char ขนาดไม่เกิน 200    
                     pub_date = models.DateTimeField('date published')
                                   #เก็บค่า
pub_date เป็น DateTime

            class Choice(models.Model):
                     poll = models.ForeignKey(Poll) 
                                   #เชื่อม ForeignKey เข้ากับ class Poll
                     choice_text = models.CharField(max_length=200)
                     votes = models.IntegerField(default=0)  
                                   #เก็บค่า votes เป็น Integer

           จากโค้ดด้านบนเป็นรูปแบบการเก็บข้อมูลซึ่งประกอบด้วยสอง class, class Poll และ Choice แต่ละ class จะเก็บเป็นตาราง ซึ่งเราสามารถ set ค่าต่างๆใน class Poll ได้โดยตรง แต่การ set ใน class Choice ต้อง set ผ่าน class Poll โดยใช้ ForeignKey เป็นตัวเชื่อม


    5. ทำการเพิ่ม 'polls', เข้าไปยัง INSTALLED_APPS ในไฟร์ settings.py เพื่อให้ ptoject รู้จัก app ดังภาพ



           เราสามารถตรวจสอบส่วนประกอบของ Poll app ที่เราได้สร้างขึ้นโดยใช้คำสั่ง

                  python manage.py sql polls


        6. ทำการ syncdb เพื่อทำการสร้างฐานข้อมูลด้วยคำสั่ง

                  python manage.py syncdb 

             แล้วใส่ superuser username, e-mail และ password ของเราเพื่อนำไปใช้ในการจัดการข้อมูลในส่วนของ admin


        7. เมื่อทำการ syncdb เรียบร้อยแล้วเราก็จะได้ฐานข้อมูลที่เราสร้างขึ้น มาถึงขั้นตอนนี้เราก็จะมาลองแก้ไขข้อมูล และแสดงผลข้อมูลต่างๆใน models ซึ่งสามารถทำได้โดยผ่าน Python shell ซึ่งเป็น API Django โดยใช้คำสั่ง 

                   python manage.py shell

 
ตัวอย่างการใช้คำสั่งการ set ข้อมูลโดยใช้ shell



       - เริ่มต้นเมื่อเรายังไม่ได้ทำการ set ค่าใดๆเลยทดลองใช้คำสั่ง
                   
                   from polls.models import Poll, Choice 
                                #เรียกใช้ class Poll และ Choice

                Poll.objects.all()  #คำสั่งเรียกค่าที่อยู่ใน objects ของ Poll

              จะเห็นได้ว่าสิ่งที่ได้หลังจากการเรียกใช้คำสั่ง Poll.objects.all() คือ [] หมายถึงยังไม่มีการเริ่ม set ค่าใดๆ

       - ทดลองทำการ set ค่า 

                  from django.utils import timezone
                                  #ทำการ import timezone
                   

               p = Poll(question="What’s new?", pub_date=timezone.now())
                                  #ทำการ set ค่า question และ pub_date ใน class Poll
               
               p.save()  #จัดเก็บค่า p
                   

               p.id  #คำสั่งแสดงค่า id ของ p                  
                  >>> 1

                  p.question  #คำสั่งแสดงค่า question ที่ได้ทำการ set               
               >>> "What’s new?"

               p.pub_date  #คำสั่งแสดง pub_date ที่ได้ทำการ set               
                >>> datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>)

               p.question = "What’s up?"  #ทำการเปลี่ยนค่า question

               p.save()

       - เมื่อทำการ set ค่าไปบ้างแล้วทดลองใช้คำสั่ง Poll.objects.all() อีกครั้งซึ่งจะทำให้ได้ผลเป็น [<Poll: Poll object>] เมื่อได้ผลดังนี้ต้องไปทำการเพิ่ม object ใน class Poll และ Choice เพื่อให้ทำการ return ค่าออกมา โดยทำการเพิ่มดังนี้
 

                from django.db import models
            


                class Poll(models.Model):
                         # ...
                         def __unicode__(self): # Python 3: def __str__(self):
                                     return self.question
 


                class Choice(models.Model):
                         # ...
                         def __unicode__(self): # Python 3: def __str__(self):
                                     return self.choice_text


             เมื่อทำการเพิ่มเสร็จแล้วทดลองใช้คำสั่ง Poll.objects.all() อีกครั้งซึ่งจะทำให้ได้ผลเป็น [<Poll: What’s up?>] คือค่าที่ return ออกมา
         - ซึ่งการ set ค่าต่างๆใน class Choice โดยใช้คำสั่งผ่าน Python shell สามารถศึกษาเพิ่มเติมได้ที่เอกสาร Django tutorial part1 : https://docs.djangoproject.com/en/dev/intro/tutorial01/

สิ่งที่ได้เรียนรู้จาก tutorial part1 
        - รู้คำสั่งต่างๆที่ใช้ run server และวิธีการ set time zone
        - ได้รู้จักเริ่มต้นการสร้าง Django App อย่างง่าย
         - ได้รู้จักวิธีการกำหนดค่าใน models
         - ได้ทดลองใช้ python shell ในการเขียน แสดงค่า และแก้ไข ไฟร์ models


=======================================================================

tutorial part 2

       โดย part นี้จะพูดเกี่ยวกับ admin site ซึ่ง admin site ก็เป็นอีกช่องทางหนึ่งสำหรับการแก้ไขและเพิ่มข้อมูลต่างๆใน models

       1. เริ่มจากการรัน server project ด้วยคำสั่ง python manage.py runserver แล้วทำการเข้าไปตาม url/admin เช่น 127.0.0.0:8000/admin


       2. ทำการ login ด้วย superuser ที่เคยได้ใส่ไปตอน syncdb ซึ่งก็จะได้หน้าหลักดังภาพ


           ซึ่งเริ่มต้นยังไม่มีการแก้ไขไฟร์ admin.py ก็จะมีเฉพาะ groups และ users ซึ่งสามารถเพิ่มและแก้ไขได้โดยการคลิกที่ add และ change


       3. ทดลองแก้ไขไฟร์ admin.py โดยเพิ่มโค้ดส่วนนี้ไปในไฟร์ admin.py

                     from polls.models import Poll
     

                   admin.site.register(Poll)

              ซึ่งส่วนนี้จะเป็นการเพิ่มตารางการแก้ไข class Poll เข้าไปใน admin site เมื่อเข้าไปยังหน้า admin site ก็จะมีตารางส่วนการแก้ไข Poll เพิ่มขึ้นมาสามารถเพิ่มและแก้ไขได้โดยกด add และ change


       4. Polls ทำการคลิก change > What's up? จะได้หน้าแก้ไขดังภาพ


              ส่วนนี้เราสามารถจัดลำดับการแสดงผลเพิ่มลำดับการจัดเก็บข้อมูลต่างๆ โดยทดลองทำการแก้ไขไฟร์ admin.py ดังนี้

                     from django.contrib import admin
                    from polls.models import Poll


                    class PollAdmin(admin.ModelAdmin):
                               fields = ['pub_date', 'question']


                    admin.site.register(Poll, PollAdmin)


              จากโค้ดจะเป็นการเพิ่ม class PollAdmin ซึ่งจะมีคำสั่ง fields = ['pub_date', 'question'] ทำหน้าที่ในการจัดการแสดงผลโดยให้ pub_date ขึ้นก่อน question จากเดิมที่ question อยู่ก่อน pub_date


        5. นอกจากนี้ยังสามารถปรับเปลี่ยนการแสดงผลต่างๆได้โดยการแก้ไขโค้ดเช่น

               from django.contrib import admin
               from polls.models import Poll
 

               class PollAdmin(admin.ModelAdmin):
                         fieldsets = [(None,{'fields': ['question']}),
                                       ('Date information', {'fields': ['pub_date']}),]
 

               admin.site.register(Poll, PollAdmin)

              จากโค้ดด้านบรจะเป็นการแยกการแสดงผลออกเป็นสองตาราง fields แรกจะแสดง 
question, fields สองจะแสดง pub_date

              from django.contrib import admin
              from polls.models import Poll


              class PollAdmin(admin.ModelAdmin):
                       fieldsets = [(None,{'fields': ['question']}),
                           ('Date information', {'fields': ['pub_date'], 
                            'classes':    ['collapse']}),]


              admin.site.register(Poll, PollAdmin)

               ส่วนโค้ดด้านบนก็จะเป็นการแยก fields question กับ pub_date แต่จะเพิ่มลูกเล่นเข้าไปในส่วนของ pub_date ให้มีการกด show หรือทำการ hide ได้

          
           6. ต่อไปก็จะเป็นส่วนการเพิ่มตารางการแก้ไขในส่วนของ class Choice เข้าไปใน admin site ซึ่งสามารถทำได้โดยการแก้ไข admin.py ดังนี้

                  from django.contrib import admin
                 from polls.models import Choice
 
                 admin.site.register(Choice)

                  โค้ดด้านบนก็เป็นการ import class Choice เข้ามาใน admin site ซึ่งก็จะสามารถ add เก็บค่า Choice text ตาม question ของ class Poll

                   from django.contrib import admin
                   from polls.models import Choice, Poll


                   class ChoiceInline(admin.StackedInline):
                               model = Choice
                               extra = 3


                   class PollAdmin(admin.ModelAdmin):
                              fieldsets = [(None,{'fields': ['question']}),
                                           ('Date information', {'fields': ['pub_date'], 
                                           'classes': ['collapse']}),]
                              inlines = [ChoiceInline]


                   admin.site.register(Poll, PollAdmin)

                 โค้ดส่วนด้านบนเป็นการเพิ่ม class Poll และ class Choice ไปใน admin site ซึ่งเมื่อกด add ที่ Polls เริ่มต้นจะมี Choice ทั้งหมด 3 Choice ให้ใส่ และสามารถเพิ่มข้อมูล Choice ได้เรื่อยๆ
                ในการจัดการ การแสดงผลในส่วนของหน้า addmin site เราสามารถศึกษาเพิ่มเติมได้ในเอกสาร Django tutorial part2 : https://docs.djangoproject.com/en/dev/intro/tutorial02/

สิ่งที่ได้เรียนรู้จาก tutorial part2
           - ได้รู้ถึงวิธิการปรับแต่งการแสดงผลในหน้า Addmin site
           - ได้รู้วิธีการเพิ่ม แก้ไข ข้อมูลใน model โดย Addmin site ได้
           - ได้รู้คำสั่งและวิธีการแก้ไขไฟร์ addmin.py เพื่อการแสดงผลบน Addmin site


=======================================================================

tutorial part3

       ในส่วนของ part 3 จะเป็นส่วนการแสดงผลข้อมูลที่เราได้เขียนลงไปในไฟร์ poll/views.py โดยจะ return ด้วยคำสั่ง HttpResponse( .. ) ผ่านไฟร์ poll/url.py และ mysite/url.py ซึ่งสามารถนำ Template มาช่วยในการเขียนส่วนของการแสดงผล
      
       1. เริ่มต้นให้ทดลองเขียนโค้ด poll/views.py เพื่อทำการแสดงผลดังนี้

            from django.http import HttpResponse
 
          def index(request):
               return HttpResponse("Hello, world. You're at the poll index.")

              จากโค้ดด้านบนจะเป็นการเขียนโค้ดเพื่อทำการแสดงผลข้อความ Hello, world. You’re at the poll index. โดยจะ return ส่วนแสดงผลไปยัง poll/url.py เพื่อไปทำการแสดงผลผ่าน mysite/url.py อีกทีหนึ่ง


      2. ทำการสร้างไฟร์ poll/urls.py แล้วทำการเขียนโค้ดในไฟร์ poll/urls.py ดังนี้

              from django.conf.urls import patterns, url
            from polls import views

            urlpatterns = patterns('',
                    url(r'^$', views.index, name='index')
            )

            จากโค้ดด้านบนจะเป็นการเรียกการแสดงผลจากไฟร์ views.py ฟังก์ชั่น index เพื่อมาแสดงผล


       3. ทำการแก้ไขไฟร์ mysite/urls.py เพื่อให้ไปเรียกไฟร์ poll/urls.py มาแสดงผลอีกทีโดยเพิ่ม

                 url(r'^polls/', include('polls.urls')),

            เข้าไปในส่วนของ urlpatterns ในไฟร์ mysite/urls.py ซึ่งจะเป็นส่วนในการเชื่อมโยงไปหาไฟร์ poll/urls.py


     4. ทำการเข้าไปยัง url ที่ได้รัน server  url/polls (http:127.0.0.1:8000/polls/) ได้ได้ผลดังรูป



      5. เราสามารถนำ url มาใช้ในการแสดงผลโดยการเขียนฟังก์ชั่นเพิ่มไปในไฟร์ polls/views.py ดังนี้ 

        from django.shortcuts import render
       from django.http import HttpResponse

       def index(request):
             return HttpResponse("Hello, world. You're at the poll index.")


       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)

         จากโค้ดด้านบนจะเป็นการเพิ่มฟังก์ชั่นขึ้นมาหลายฟังก์เพื่อแยกการแสดงผลที่แต่กต่างกันและเป็นการรับค่าตัวเลขจาก url มาแสดงด้วย ซึ่งการแสดงผลเมื่อเรียกใช้ฟังก์ชั่น index จะแสดงข้อความ Hello, world. You're at the poll index. เมื่อเรียกใช้ฟังก์ชั่น detail จะแสดงข้อความ You're looking at poll 'ตัวเลขที่ใส่ใน url'. เมื่อเรียกใช้ฟังก์ชั่น results จะแสดงข้อความ You're looking at the results of poll 'ตัวเลขที่ใส่ใน url'. เมื่อเรียกใช้ฟังก์ชั่น vote จะแสดงข้อความ You're voting on poll 'ตัวเลขที่ใส่ใน url'.


      6. เมื่อมีการเพิ่มฟังก์ชั่นการแสดงผลไปในไฟร์ polls/views.py แล้วก็จะมาถึงส่วนสร้าง url เพื่อทำการเรียกใช้ฟังก์ชั่น โดยเราจะไปทำการแก้ไขไฟร์ polls/urls.py ดังนี้

       from django.conf.urls import patterns, url
       from polls import views


       urlpatterns = patterns('',
                 # url/polls/5/
                 # เป็นส่วนการเรียกฟังก์ชั่น detail มาแสดงผล
                 url(r'^(?P<poll_id>\d+)/$', views.detail, name='detail'),

                 # url/polls/5/results/
                 # เป็นส่วนการเรียกฟังก์ชั่น resulte มาแสดงผล                
                 url(r'^(?P<poll_id>\d+)/results/$', views.results,
                             name='results'),

                 # url/polls/5/vote/
                 # เป็นส่วนของการเรียกฟังก์ชั่น vote มาแสดงผล
                 url(r'^(?P<poll_id>\d+)/vote/$', views.vote, name='vote'),

                 # url/polls/
                 # เป็นส่วนของการเรียกฟังก์ชั่น index มาทำการแสดงผล
                 url(r'^$', views.index, name='index')
)

          จากโค้ดเป็นการเขียน url เพื่อเรียกใช้ฟังก์ชั่นโดย url/polls/5/ จะเรียกใช้ฟังก์ชั่น detail มาแสดงผล url/polls/5/resulte/ จะเรียกใช้ฟังก์ชั่น resulte มาแสดงผล url/polls/5/vote จะเรียกใช้ฟังก์ชั่น vote มาแสดงผล url/poll/ จะเรียกฟังก์ชั่น index มาแสดงผล


       7. เราสามารถเขียนโค้ดเพื่อเรียกการแสดงผล question ที่ได้ใส่ลงไปใน tutorial part1 และ part2 ที่เป็นการแสดงผลผ่าน Python Shell และ admin site ซึ่งมาถึง part3 เราจะทำการเขียนโค้ดเพื่อการแสดงผลโดยต้องทำการแก้ไขตรงไฟร์ polls/views.py โดยแก้ไขฟังก์ชั่น index() ดังนี้

          from django.shortcuts import render
          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)

         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)
 
         def vote(request, poll_id):
             return HttpResponse("You're voting on poll %s." % poll_id)

          จากโค้ดจะเป็นการเรียก class Poll ใน polls/models.py ออกมาทำการแสดงผล question ซึ่งเมื่อเราเข้าไปยัง url/polls/ ก็จะมีข้อความที่เก็บใน question แสดงอยู่

           ซึ่งในส่วนการแสดงผลนี้เราสามารถเขียนแยกเป็น Template ได้ ในที่นี้จะยกตัวอย่างโดยการสร้าง directory template ไว้ใน directory polls polls/template/poll/index.html ทำการใส่ path template ในไฟร์ setting.py ของ directoty project


            แล้วเราจะทำการแก้ไขสองไฟร์คือ ไฟร์ template/poll/index.html และไฟร์ polls/view.py ซึ่งไฟร์ template/polls/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 %}

          จากโค้ดเป็น form ส่วนการแสดงผล question ซึ่งจะเชื่อมโยงกับไฟร์ polls/view.py โดยทำการแก้ไขไฟร์

           from django.template import RequestContext, loader
           from django.http import HttpResponse
           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))


          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/view.py ซึ่งจะเป็นส่วนที่ดึง form ที่่เขียนไว้มาแสดงผล เมื่อเราเข้าไปยัง url/polls/ ก็จะมีข้อความที่เก็บใน question แสดงอยู่
          ซึ่งใน part นี้การเขียนออกมาในรูปของ form มีอีกหลายรูปแบบซึ่งสามารถศึกษาเพิ่มเติมได้ที่เอกสาร Django tutorial part3 : https://docs.djangoproject.com/en/dev/intro/tutorial03/


          8. Http404 หรือ get_object_or_404() เป็น function ของ django ที่ช่วยในการดัก exception ซึ่งเราจะใช้เมื่อมีการเรียกใช้งานจาก url ซึ่งการเรียกใช้นั้นไม่ตรงกับเงื่อนไขไดๆในโค้ด ก็จะกลายเป็น exception แสดงหน้าของ Http404 เพื่อให้รู้ว่า url ที่ทำการเรียกไม่ตรงกับเงื่อนไขไดๆ หรือไม่มีในข้อมูล ซึ่งตัวอย่างการใส exception ก็เช่นทำการแก้ไขฟังก์ชั่น detail ในไฟร์ polls/view.py ดังนี้

           from django.http import Http404
           from django.shortcuts import render
 

           #....

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


                #....

          สร้างไฟร์ template/polls/detail.html แล้วทำการแก้ไขไฟร์ดังนี้

           {{ poll }}

          จากโค้ดเมื่อเข้าไปยัง url/polls/1 ก็จะแสดง question poll_id 1 ซึ่งเมื่อเปลี่ยนเลย 1 เป็นเลขอื่นเช่น 2 ก็จะแสดงหน้า Http404 ซึ่งเป็น exception ที่สร้างขึ้น เนื่องจาก question poll_id 2 ไม่มีในฐานข้อมูล



           9. url in template
                     url เป็นอีกอย่างหนึ่งที่สำคัญที่ใช้ใน template ซึ่งก็มีรูปแบบที่ง่ายต่อการเขียน และง่ายต่อการลิ้ง url ไปยังฟังก์ชั่นต่างๆ ซึ่งตัวอย่างเช่น แก้ไขไฟร์ urls.py ใน directory project จาก

                url(r'^polls/', include('polls.urls')),

        เป็น

               url(r'^polls/', include('polls.urls', namespace="polls")),

       และแก้ไขไฟร์ 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>

        ซึ่งจะทำให้ง่ายต่อการเรียกใช้และมีความยืดหยุ่นมากกว่า


สิ่งที่ได้เรียนรู้จาก tutorial part3
          - ได้รู้ถึงวิธีการสร้างส่วนการแสดงผลของ Django app ซึ่งมีหลักการเหมือนกับการสร้างส่วนแสดงผลของไฟร์ project
          - ได้รู้วิธีการนำส่วนการแสดงผลมาทำในรูปของ Template ใน Django app
          - ได้รู้การทำส่วนแสดงผลให้แสดง question
          - ได้รู้หลักการใช้ Http404
          - การใช้ url ใน template


=======================================================================

tutorial part 4

       part นี้จะพูดถึงการเขียน form ไว้ในไฟร์ html เพื่อเรียกไปแสดงผลผ่าน Django app และจะพูดถึงโค้ดส่วน view.py โดยจะทำการเขียนแยกเป็น class เพื่อความสะดวกในการเรียกใช้งาน และการเขียนโค้ดมากขึ้น


        1. เริ่มจากการเขียน form โดยการสร้างไฟร์ template/polls/detail.html ทำการแก้ไขไฟร์

               <h1>{{ poll.question }}</h1>

              {% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
              <form action="polls.views.vote" method="post">

             {% csrf_token %}
             {% for choice in poll.choice_set.all %}
                      <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" />
                      <label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br />
             {% endfor %}

             <input type="submit" value="Vote" />
             </form>

 

             จากโค้ดเป็น form การแสดงผลโดยจะแสดงข้อความ question ตามด้วยข้อความ
You didn't select a choice. ตามด้วย choice ทั้งหมดให้เลือก และปุ่ม vote


        2. ทำการแก้ไขไฟร์ poll/view.py เพื่อทำการเชื่อมต่อและเรียกใช้ form ที่ได้เขียนไว้ซึ่งจะทำการแก้ไขดังนี้

          from django.shortcuts import get_object_or_404, render
          from django.http import HttpResponseRedirect, HttpResponse
          from django.core.urlresolvers import reverse
          from polls.models import Choice, Poll
       

          #....

          def vote(request, poll_id):
                p = get_object_or_404(Poll, pk=poll_id)


                try:
                     selected_choice = p.choice_set.get(pk=request.POST['choice'])


                except (KeyError, Choice.DoesNotExist):
                    
# Redisplay the poll voting form.
                     return render(request, 'polls/detail.html', {'poll': p,
                             'error_message': "You didn't select a choice.",
                     })


                else:
                     selected_choice.votes += 1
                     selected_choice.save()
                    
# Always return an HttpResponseRedirect after successfully dealing
                         # with POST data. This prevents data from being posted twice if a
                         # user hits the Back button.

                     return HttpResponseRedirect(reverse('polls:results', args=(p.id,)))


            #....

          ซึ่งจากโค้ดจะเป็นการสร้างส่วนของการ vote คือ render detail.html มาแสดงผล และเมื่อมีการ vote ก็จะมีการไป Redirect url ไปยัง class resuits ซึ่ง results จะแสดงค่า vote ของแต่ละ choice และหน้า results จะมี Vote again? เพื่อลิ้งกลับมาหน้า detail
         

           3. ทำการสร้างไฟร์ template/polls/results.html และแก้ไขดังนี้

             <h1>{{ poll.question }}</h1>
             <ul>
              {% for choice in poll.choice_set.all %}
                      <li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
              {% endfor %}
              </ul>
              <a href="{% url 'polls:detail' poll.id %}">Vote again?</a>

            

           4. ทำการแก้ไข class results ใน polls/views.py

            from django.shortcuts import get_object_or_404, render

           def results(request, poll_id):
                  poll = get_object_or_404(Poll, pk=poll_id)
                  return render(request, 'polls/results.html', {'poll': poll})


 เมื่อเข้าไปยัง url/poll/1/vote/ ก็จะได้ผลดังรูป




             5. generic views เป็นอีกตัวช่วยหนึ่งของ django เป็น api ที่สร้างขึ้นเพื่อช่วยในการเขียนโค้ดใน views มีความเป็นระบบมากขึ้น ทำให้โค้ดอ่านง่ายและดูสั้น ง่ายต่อการแก้ไข ซึ่งตัวอย่างการใช้ generic เช่น ทำการแก้ไขไฟร์ polls/views.py ดังนี้

         ...
         from django.views import generic
         ...

         class IndexView(generic.ListView):
                  template_name = 'polls/index.html'
                  context_object_name = 'latest_poll_list'
                  def get_queryset(self):
                        """Return the last five published polls."""
                  return Poll.objects.order_by(’-pub_date’)[:5]

 
        class DetailView(generic.DetailView):
                 model = Poll
                 template_name = 'polls/detail.html'

 
        class ResultsView(generic.DetailView):
                model = Poll
                template_name = 'polls/results.html'

 
        def vote(request, poll_id):
               ....
       จะเห็นได้ว่าการใช้ generice ต้องทำการ import generice แล้วทำการเขียนแยกเป็น class ซึ่งทำให้ดูง่ายขึ้น       
       ทำการแก้ไขไฟร์ polls/urls.py โดยแก้ไข url ตามรูปแบบ generice
   
        from django.conf.urls import patterns, url
        from polls import views
 

        urlpatterns = patterns('',
                url(r'^$', views.IndexView.as_view(), name='index'),
                url(r'^(?P<pk>\d+)/$', views.DetailView.as_view(), name='detail'),
                url(r'^(?P<pk>\d+)/results/$', views.ResultsView.as_view(), name='results'),
                url(r'^(?P<poll_id>\d+)/vote/$', views.vote, name='vote'),
)


      เมื่อมีการเข้าไปยัง url ที่ runserver ก็จะได้ผลเหมือนเดิม เหมือนกับตอนที่ไม่ได้ใช้ generice ซึ่งสามารถศึกษาเพิ่มเติมได้ในเอกสาร tutorial part 4 : https://docs.djangoproject.com/en/dev/intro/tutorial04/

สิ่งที่ได้เรียนรู้จาก tutorial part4
     - ได้รู้วิธีการประยุคต์ใช้ form ใน template
      - วิธีการใช้ generic views

=======================================================================
  

วันพุธที่ 27 พฤศจิกายน พ.ศ. 2556

งานนิทรรศการ 50 ปี คณะวิศวกรรมศาสตร์ มจพ.

งานนิทรรศการ 50 ปี คณะวิศวกรรมศาสตร์ มจพ.

        

        งานนิทรรศการ 50 ปี คณะวิศวกรรมศาสตร์ มจพ. เป็นงานที่จัดขึ้นใต้ตึก 81 ตึกคณะวิศวกรรมศาสตร์ มหาวิทยาลัยพระจอมเกล้าพระนครเหนือ เพื่อให้สาขาต่างๆ ในคณะวิศวกรรมศาสตร์ นำผลงานต่างๆมาแสดงเช่น หุ่นยนต์ ที่หลายๆสาขาได้สร้างขึ้นมาแสดงในงานให้คนในงานได้ชมผลงาน และในงานยังมีบูทบริษัทต่างๆ ที่เกี่ยวข้องกับคณะวิศวกรรมศาสตร์มารับสมัคงาน รับสมัคฝึกงาน และให้คำแนะนำความรู้เกี่ยวกับการทำงานต่างๆ


    Thinknet เป็นบริษัทหนึ่งที่มาจัดบูทเพื่อให้คำแนะนำเกี่ยวกับการทำงาน การรับสมัคงาน การรับสมัคฝึกงาน เป็นหนึ่งบริษัทที่พัฒนาด้าน software มีงานทางด้านการพัฒนา Framework และ APIs สำหรับ Web Application โดยใช้ ( PHP, MySQL, HTML/HTML5, JavaScript ) พัฒนา API ของ Web service interface ของทั้ง Web Application และ Mobile Apps ค้นคว้าและวิจัยตามที่ได้รับมอบหมาย อาทิ Map Routing Algorithm, Map Data Optimization, Social API Integration ฯลฯ ออกแบบ Database เพื่ิอใช้ Web Application และงานทางด้าน software อีกหลายๆประเภท จึงเป็นอีกทางเลือกหนึ่งสำหรับคนที่สนใจและอยากพัฒนาด้าน software ให้มากยิ่งขึ้น

 =======================================================================

วิธีการใช้งาน Django เบื้องต้น

วิธีการใช้งาน Django เบื้องต้น

Django คือ web framework ที่ใช้พัฒนา web application ซึ่งพัฒนาโดยใช้ภาษา python.


 -สามารถ download และ install Django ได้ที่ 
          https://www.djangoproject.com/download/


 -เริ่มต้นการใช้งาน Django
         1. เปิด command line ใช้คำสั่ง cd เข้าไปยัง part ที่ต้องการสร้างโปรเจค


         2. ทำสร้างโปรเจคเพื่อเริ่มใช้งาน Django โดยใช้คำสั่ง  django-admin.py startproject ตามด้วยชื่อโปรเจค ในที่นี้จะใช้ชื่อโปรเจคชื่อ myjango ก็จะได้คำสั่งคือ

               django-admin.py startproject myjango


         3. เมื่อทำการสร้างโปรเจคเสร็จแล้วจะมี Directory ที่อยู่ในโปรเจคดังนี้
              จะเห็นได้ว่าจะมีชื่อ Directory ของ project ที่ซ้ำกันเราสามารถที่จะเปลี่ยนชื่อ Directory แรกของ project เพื่อป้องกันการสับสนโดยใช้คำสั่ง mv ชื่อproject ชื่อที่ต้องการเปลี่ยน เช่น

                mv myjango jango                          
             

          4. ซึ่งเบื่องต้นเราจะศึกษาการทำงานของ 2 ก่อนไฟร์ คือ urls.py และไฟร์ view.py(เป็นไฟร์ที่เราต้องสร้างขึ้นใน Directory myjango ชึ่งจะทำหน้าที่เก็บโค้ดที่เราเขียนขึ้นเพื่อทำการแสดงผล)


          5. ทำการสร้างไฟร์ view.py ทดลองเขียน Source Code ในไฟล์ view.py ดังนี้

             from django.http import HttpResponse

           def hello(request):
                   return HttpResponse("Hello World website with python")


          จากตัวอย่าง Source Code ด้านบนบรรทัดแรกคือการ import class HttpResponse ซึ่งอยู่ในโมดูล django.http โดย class ดังกล่าวมีไว้สำหรับการทำงานในส่วนของการแสดงผล
          ทำการประกาศ Function ชื่อ hello ซึ่ง Function นี้จะทำการ return Hello world website with python ออกมาด้วยคำสั่ง HttpResponse


         6. แก้ไขไฟล์ urls.py ซึ่งเป็นไฟล์ที่มีไว้สำหรับการ Mapping ระหว่าง URLs กับ View function โดยเพิ่ม url(r'^hello/$', 'myjango.views.hello'), เข้าไปใน function urlpatterns ดังนี้

             from django.conf.urls import patterns, include, url

           from django.contrib import admin
           admin.autodiscover()

           urlpatterns = patterns('',
                     # Examples:
                     # url(r'^$', 'myjango.views.home', name='home'),
                     # url(r'^blog/', include('blog.urls')),

                      url(r'^admin/', include(admin.site.urls)),
                      url(r'^hello/$', 'myjango.views.hello'),
            )


          จากตัวอย่าง Source Code ด้านบน คือ url(r'^hello/$', 'myjango.views.hello'), คือการ Mapping ว่าถ้า URLs นั้นเป็น [HOST:PORT]/hello/ ให้ทำการเรียกใช้ Function hello (hello คือ ชื่อ Function ใน views.py)


           7. เปิด command line ใช้คำสั่ง cd เข้าไปยัง part ที่มีไฟร์ manage.py แล้วทำการรัน server ด้วยคำสั่ง python manage.py runserver เพื่อทำการรันและแสดงผลโค้ดที่ได้เขียนไว้


           8. ทดสอบการรัน Server โดยการเปิดเบราว์เซอร์แล้วเข้าไปยัง url : 127.0.0.1:8000/hello หากไม่พบข้อผิดพลาดใด ๆ จะปรากฏหน้าจอดังรูปภาพ


               เท่านี้ก็จะได้การใช้งาน django แสดงข้อความ string แบบง่ายๆแล้ว

=======================================================================

วันอาทิตย์ที่ 24 พฤศจิกายน พ.ศ. 2556

week 3

week 3

 1.เขียนโปรแกรมโดยใช้ภาษา python ปรับปรุงการแสดงผลของไฟร์ html จากการดึงข้อมูลจากไฟร์ .txt และนำข้อมูลที่ดึงจากไฟร์ .txt ไปเขียนเป็นไฟร์ .csv



ส่วนของ code จะแสดง:
-ส่วนของการแสดงผลบน Browser จากเดิมที่สร้างไฟร์ html แยกเป็นสองส่วนคือส่วนของ home และส่วนการเก็บข้อมูลของแต่ละบุคคล ได้ทำการปรับปรุงโดยเพิ่ม ปุ่ม Previous, Next, Home ในหน้าแสดงข้อมูลส่วนตัว เพื่อที่จะสามารถ กดปุ่ม Previous เพื่อกลับไปดูข้อมูลคนก่อนหน้า กดปุ่ม Next เพื่อไปดูข้อมูลคนต่อไป กดปุ่ม Home เพื่อกลับไปยังหน้า home
-ส่วนของหน้า Home ได้ทำการปรับปรุงจากเดิมแสดงเฉพาะระหัสนักศึกษา ก็ได้เพิ่มชื่อนักศึกษาเข้าไปด้วย
-ในส่วนของการแปลงเป็นไฟร์ .csv ได้เปลี่ยนข้อมูลจาก / เปลี่ยนเป็น , แทนเพื่อให้สามารถแยกข้อมูลแสดงผลเป็นตารางได้ 
 
คำอธิบาย code:
-โด้ดได้ทำการปรับการเขียนโดยแยกเป็นฟังก์ชั่น เพื่อแบ่งหน้าที่การทำงาน ง่ายต่อการอ่าน และการเรียกใช้งาน
-ส่วนแรกจะทำการเรียกฟังก์ชั่น read_file() เพื่อทำการอ่านข้อมูลจากไฟร์ .txt ออกมาทั้งหมดเก็บเป็นข้อมูลแบบ dictionary แล้วทำการ sort ข้อมูลเรื่องตามระหัสนักศึกษา
-ในฟังก์ชั่น read_file() เมื่อทำการ sort ข้อมูลเสร็จแล้วก็จะทำการเรียกฟังก์ชั่น html_home(key) และฟังก์ชั่น html_file(dic, key, list_profile) เพื่อทำการเขียนไฟร์ home.html และ profile.html หลังจากนั้นก็จะเรียกฟังก์ชั่น changeto_csv(dic, list_profile)
-ส่วนของฟังก์ชั่น html_home(key) ก็จะทำการเขียน home.html โดยใช้ parameter ชื่อ key ที่เก็บค่าระหัสนักศึกษาและชื่อที่ได้ทำการ sort เรียบร้อยแล้ว ในการเขียน home.html แสดงระหัสนักศึกษาตามด้วยชื่อนักศึกษา และทำการเขียนเป็นลิ้งไปยังชื่อไฟร์ที่เก็บข้อมูลนักศึกษาคนนั้น
-ส่วนของฟังก์ชั่น html_file(dic, key, list_profile) จะทำการเขียน profile.html โดยใช้ parameter ชื่อ dic ที่เก็บข้อมูลนักศึกษาทั้งหมดที่ sort เรียบร้อยแล้ว, list_profile เก็บหัวข้อข้อมูลที่จะแสดงทั้งหมด, key จะนำมาใช้ข้อมูลส่วนระหัสนักศึกษา ในการเขียน profile.html จะเขียนแสดงข้อมูลทั้งหมดเป็นตารางและ สร้างปุ่มเพื่อลิ้งไปไฟร์ profile.html ก่อนหน้า ปุ่มลิ้งไปไฟร์ file.html ถัดไป ปุ่มลิ้งไปไฟร์ home.html
-ส่วนของฟังก์ชั่น changeto_csv(dic, list_profile) จะนำข้อมูลที่อยู่ใน parameter ชื่อ dic มาเรียงโดยใช้เครื่องหมาย , ขั้นระหว่างข้อมูลแทนเครื่องหมาย / และเขียนข้อมูล 1 คนต่อ 1 บรรทัด save เป็นไฟร์ .csv


ตัวอย่าง Source code ที่ได้ทำการเขียน:
 #--------------------#
#24-11-2013
#klanarong raluek
#--------------------#


import webbrowser, os

#function write home.html
def html_home(key):
    num_file = 1
    home = """
        <html>
        <head>
            <title>Index </title>
        </head>
        <body background = "002.jpg">
        &nbsp;<font size='7' color = 'orange'><B> Student ID </B></font>
        <hr size=4>
        <UL Type='Disc'>
        """
    for i in range(len(key)):
        home += "<Li><font size='4'><A href='"+ 'profile'+str(num_file) +"'><I><B><font color='black'>"+str(key[i][0])+" "+str(key[i][1])+"</A></font></I></B><BR>"      
        num_file += 1
    home += """</UL> </body>
        </html>
        """
    htmlFile = open('Home.html', "w+")
    htmlFile.write(home)
    htmlFile.close()

#function write profile.html
def html_file(dic, key, list_profile):
    num_file = 1
    my_html = ""
    for i in range(len(dic)):
        my_html = """
        <html>
        <head>
            <title>Index </title>
        </head>
        <body background = "002.jpg">
            &nbsp;<font size='7' color = 'orange'><B>"""+ str(key[i][0]) +"""</B></font>
            <hr size=4><center>
            """
        for j in range(len(dic[i][1])):
            my_html += "<table BORDER = 4 ><tr><td width = '100'><B><I><font size='4' color = blue>"+ list_profile[j+1] +"</font></I></B></td>"
            my_html += "<td width = '300'><B><I><font size='4' color = blue>"+ dic[i][1][j] +"</font></I></B></td></tr>"  
        my_html += "</table>"
        if i == 0:
            my_html += "<font size='4'><A href='"+ 'profile'+str(num_file+1) +"'><font color='black'>Next</A></font><BR>"
            my_html += "<font size='4'><A href=' Home.html '><font color='black'>Home</A></font><BR>"
        elif i == len(dic)-1:
            my_html += "<font size='4'><A href='"+ 'profile'+str(num_file-1) +"'><font color='black'>Previous</A></font><BR>"
            my_html += "<font size='4'><A href=' Home.html '><font color='black'>Home</A></font><BR>"
        else:
            my_html += "<font size='4'><A href='"+ 'profile'+str(num_file-1) +"'><font color='black'>Previous</A></font>"
            my_html += "<font size='4' color = black>|</font>"
            my_html += "<font size='4'><A href='"+ 'profile'+str(num_file+1) +"'><font color='black'>Next</A></font><BR>"
            my_html += "<font size='4'><A href=' Home.html '><font color='black'>Home</A></font><BR>"
        my_html += """
        </center></body>
        </html>
        """
        htmlFile = open('profile'+str(num_file), "w+")
        htmlFile.write(my_html)
        htmlFile.close()
        num_file += 1

#function chang to file.csv
def changeto_csv(dic, list_profile):
    string = ""
    for i in range(len(list_profile)):
        string += list_profile[i]
        if i < len(list_profile)-1:
            string += ','
        else :
            string += '\n'
    for i in range(len(dic)):
        string += str(dic[i][0])+','
        for j in range(len(dic[0][1])):
            string += dic[i][1][j]
            if j < len(dic[0][1])-1:
                string += ','
            else :
                string += '\n'
    file_csv = open('list_profile.csv', "w+")
    file_csv.write(string)
    file_csv.close()

#function read file.txt
def read_file():
    key = {}
    dic = {}
    list_profile = []
    file_txt = open('list_profile.txt', 'r')
    num_line = file_txt.read()
    num_line = num_line[:-1].split("\n")
    for i in num_line:
        list_data = i[:-1].split("\\")
        if list_data[0] == 'StudentID ':
            list_profile = list_data
            continue
        key[long(list_data[0])] = list_data[1]
        dic[long(list_data.pop(0))] = list_data
    dic = sorted(dic.items())
    key = sorted(key.items())
    html_home(key)
    html_file(dic, key, list_profile)
    changeto_csv(dic, list_profile)
    webbrowser.open('Home.html', new=1)   #run file html

read_file()
 
ผล output ที่ได้:

ภาพแสดงข้อมูลส่วนตัว เมื่อมีการคลิกลิ้งไฟร์ที่เก็บข้อมูลของแต่ละคน

ภาพแสดงข้อมูลส่วนตัว เมื่อมีการคลิกลิ้งไฟร์ที่เก็บข้อมูลของแต่ละคน

ภาพแสดงหน้า home

ภาพแสดงข้อมูลส่วนตัว เมื่อมีการคลิกลิ้งไฟร์ที่เก็บข้อมูลของแต่ละคน


=======================================================================