วันพฤหัสบดีที่ 5 กุมภาพันธ์ พ.ศ. 2558

Chapter 5 : Saving User Input

 Wiring Up Our Form to Send a POST Request

จากบทที่แล้ว เราไม่สามารถบันทึกค่าอินพุทที่รับเข้ามาได้ แต่เรามี HTML POST request method 

ให้ทำการแก้ไข

lists/templates/home.html. 



- รัน FT -
ผลลัพธ์จะได้


จะเห็นว่าเกิดการ unexpected failure มีวิธีแก้ไขดังนี้
     - เพิ่ม print statements เพื่อดูข้อความของ page
     - แก้ไขข้อผิดพลาดนั้นๆ
     - ทดลองดูเว็บไซต์ด้วยตัวเอง
     - ใช้คำสั่ง time.sleep เพื่อหยุดการทดสอบระหว่างการทำงาน



โดยจะทำการเลือกใช้ time.sleep และเพิ่มเติมโค้ดใน FT

ผลลัพธ์ที่ได้ จะได้หน้า DEBUG เพื่อโชว์ CSRF error
Django DEBUG page showing CSRF error
Django’s CSRF protection involves placing a little auto-generated token into each generated form, to be able to identify POST requests as having come from the original site. - การป้องกัน CSRF ของ Django มีไว้เพื่อที่จะสร้าง token ไปในแต่ละฟอร์ม ไว้เพื่อระบุ POST request ที่รับเข้ามาจากไซต์เดิม -

 แก้ไขเพิ่มเติมใน lists/templates/home.html. (เพิ่ม {% csrf_token %} )

 

 Django จะทำการ Render input แบบ type = "hidden" เพื่อที่จะเก็บ CSRF token และทดลองรัน FT ใหม่ จะได้ว่า
AssertionError: False is not true : New to-do item did not appear in table
 
แต่เรายังมี teim.sleep ซึ่งจะทำให้เทสมันหยุด ตอน final screen ให้ทำการลบ time.sleep ได้เลย (เอา DEBUG ออกให้เป็น home page ธรรมดา) ใน item text มันจะหายไปเมื่อเรา submit ฟอร์ม และ page ก็จะ Refresh เพื่อให้เป็น form ว่างๆอีกครั้ง และทดลองรัน FT ใหม่ จะได้ว่า
    # "1: Buy peacock feathers" as an item in a to-do list table
    inputbox.send_keys(Keys.ENTER)

    table = self.browser.find_element_by_id('id_list_table')

Processing a POST Request on the Server
ใน lists/tests.py ให้เพิ่มโค้ดเพิ่มเข้าไป ดังนี้


เมื่อรัน python3 manage.py test จะขึ้น Error 

    AssertionError: 'A new list item' not found in '<html>

ให้ทำการเพิ่มเติมโค้ดใน lists/views.py เพื่อเพิ่มส่วน POST submission ไปที่ตารางใน home page template.


เมื่อรัน unit test => OKAY !!!

Passing Python Variables to Be Rendered in the Template

ใน lists/templates/home.html. ให้เพิ่มโค้ด



เราจะดูค่าใน new_item_next ได้อย่างไร แล้วเราจะส่งผ่านส่วนของ variable ไปที่ template ได้อย่างไร 

เรามีฟังก์ชั่น render_to_string แล้วใน Unit Test เพื่อที่จะ render template ด้วยตัวเราเอง และเปรียบเทียบกับ return ของ HTML ที่ออกมา และเราก็จะไปเพิ่มส่วนของ variable ที่เราต้องการจะส่งผ่าน

เพิ่มโค้ดในส่วนของ lists/tests.py. 


 เมื่อเรารัน unit test จะได้ผลลัพธ์ว่า 

self.assertEqual(response.content.decode(), expected_html) AssertionError: 'A new list item' != '<html>\n <head>\n 
[...]

โอเค เราทดสอบให้มัน return ค่าอะไรสักอย่างได้แล้ว ต่อไปก็ rewrite ที่ view ของเรา และบอกให้มัน pass the POST parameter ไปที่ template

เพิ่มโค้ดในส่วนของ lists/views.py 


และเมื่อรัน จะได้ผลลัพธ์

ถ้าจำ reading tracebacks ได้ จะเห็นว่าเราจะต้องให้มัน get ค่า ' ' ออกมาถ้า 'item_next' ผิดพลาด
ให้แก้โค้ดในส่วนของ lists/views.py 

 ผลลัพธ์ของ Unit Test
Unit test ผ่าน แต่ !! FT ยังไม่ผ่าน และขึ้น Error ว่า

ให้ทำการเข้าไปแก้โค้ดใน functional_test



แต่ยัง Error

AssertionError: False is not true : New to-do item did not appear in table -- its text was: Buy peacock feathers

ให้ลองใช้ assertIn แทน assertTrue (แทนที่ ทั้ง 6 บรรทัดนั้น)



แต่ก็ยัง Error เพราะ หา 1: Buy [...] ไม่เจอ (เจอแต่ Buy [...] )
ให้ทำการแก้ไข ที่ lists/templates/home.html.

 รัน FT จะได้ว่า Finish the test!

***********************
The unit-test/code cycle is sometimes taught as Red, Green, Refactor:
  • Start by writing a unit test which fails (Red).
  • Write the simplest possible code to get it to pass (Green), even if that means cheating.
  • Refactor to get to better code that makes more sense.
***********************
ทำการเพิ่มเติมโค้ด ใน FT 
 

แต่เมื่อรัน FT จะพบว่า Error
AssertionError: '1: Buy peacock feathers' not found in ['1: Use peacock feathers to make a fly']  
หมายถึงว่า เราพิมพ์ '1: Use peacock feathers to make a fly' เข้าไปแต่จริงๆแล้วในฟังก์ชั่นมันเป็น '2: [...]' เลยทำให้ไม่เจอ '1: Use peacock feathers to make a fly'

Three Strikes and Refactor

ให้ทำการ commit GIT โดยใช้คำสั่ง 

จากนั้นกลับไปที่ FT และเข้าไปเพิ่ม method ระหว่าง tear_Down และ first test


และแก้ไขเป็น


และเมื่อรัน FT อีกครั้ง จะพบว่า Error เหมือนเดิม
AssertionError: '1: Buy peacock feathers' not found in ['1: Use peacock feathers to make a fly']

ให้ทำการ commit GIT อีกครั้ง โดยใช้คำสั่ง 



The Django ORM and Our First Model

An Object-Relational Mapper (ORM) ก็คือ layer ของ absrtaction เพื่อที่จะเก็บ data ใน database ด้วยรูปแบบของ ตาราง แถว คอลัมน์ มันช่วยให้เราทำงานกับฐานข้อมูลโดยใช้คำเปรียบเปรยเชิงวัตถุที่คุ้นเคย ซึ่งทำงานได้ดีกับ code , class ถูกเก็บไปในรูปแบบตาราง attributes ถูกเก็บไว้ใน คอลัมน์ และตัวอย่างในแต่ละ class ก็หมายถึงแถวของข้อมูลของ database

ทำการสร้าง Class ใน lists/tests.py

Let’s try running the unit test.
 

ให้ไปทำการแก้ไขโค้ดใน lists/models.py. 

และเมื่อรัน ก็จะพบว่า object ไม่มี attribute 'save' จึงต้องเปลี่ยนโค้ด จาก object เป็น models.Model 



Our First Database Migration

 ทดลองรัน Unit Test จะพบ Error django.db.utils.OperationalError: no such table: lists_item
 ให้ทำการรัน 2 คำสั่งนี้ 


 


งานของ ORM คือ เป็น Model ของ database และอีกอย่างก็คือเกี่ยวกับการสร้าง database เราเรียกว่า migrations และมันมีความสามารถในการเพิ่มและลบตารางและคอลัมน์ การเปลี่ยนแปลงอยู่บนไฟล์ models.py วิธีที่จะสร้างการย้ายฐานข้อมูลครั้งแรกก็คือ การใช้คำสั่ง makemigrations


The Test Gets Surprisingly Far

run the test 

ผลลัพธ์ที่ได้

แก้โค้ดที่ views/models.py




* รออัพเดต *

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

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