วันพุธที่ 12 กรกฎาคม พ.ศ. 2560

commit เพิ่มเติม : เพื่ม userstory, bookmark

>> add userstory
ทำการเพิ่ม userstory ใน functional tests

>> add bookmark for user
เพิ่มระบบ Bookmark โดยการสร้าง model ขึ้นมาอีกตัวชื่อ bookmark
มีความสัมพันธ์กับ model User  1 ต่อ 1
มีความสัมพันธ์กับ model Person แบบ Many to Many ซึ่งจะทำให้ bookmark ตัวนึงเก็บได้หลาย person

ตัวอย่างการเรียกใช้เมื่อมีความสัมพันธ์แบบ many to many เช่น
bookmark.person.add(person1)
เป็นการเพิ่มคน (person1) เข้าไปใน bookmark


>> check if user is logged in before retrive bookmark data
แก้ไขให้แสดงข้อมูลตามปกติ เมื่อไม่ได้ล็อกอิน
เนื่องจากของเดิมไปดึงข้อมูลของ AnoymousUser ทำให้เกิด Error

>> only show bookmark when logged in.
แสดง bookmark เฉพาะตอนล็อคอินแก้ใน template ของหน้า ที่สามารถเพิ่ม bookmark ได้

วันพุธที่ 14 มิถุนายน พ.ศ. 2560

commit เพิ่มเติม : เพื่มเปลี่ยน theme เข้าไปในเว็บ

add change theme

ได้เพิ่มการเปลี่ยน theme
ใช้ theme จาก https://bootswatch.com/


ใช้ session ในการเก็บค่า theme


จาก
The session framework lets you store and retrieve arbitrary data on a per-site-visitor basis

session จะทำให้สามารถเก็บและดึงข้อมูลมาใช้ได้ ในการเยี่ยมชมเว็บไซต์ครังนี้

 แก้ไขในไฟล์ html ทุกไฟล์
โดยการเพิ่ม ตัวแปร theme

ไปเพื่มในไฟล์ views.py ให้ดึงค่า theme จาก session หากไม่เจอค่า theme จะเอาค่า 'css/boostrap.min.css' มาใช้เลย














ฟังก์ชั่นเปลี่ยน theme โดยจะดึงค่าจาก GET( ตัวแปร theme ) มาเพื่อเทียบว่าใช้ theme อันไหน
แล้วตั้งค่าใน session

วันจันทร์ที่ 12 มิถุนายน พ.ศ. 2560

commit เพิ่มเติม : เปลี่ยน password ของ user

commit
ใน commit นี้เพิ่มในส่วนการเปลี่ยน password โดยจะใช้ระบบ authen ของ django ทำเลย

PasswordChangeForm
เป็น form ของ django สำหรับใช้เปลี่ยน password
มันจะเอา user argument มาเป็น constructor

update_session_auth_hash
ใช้เพื่อไม่ให้ user ต้องล็อคอินอีกครั้ง , เหตุผลด้านความปลอดภัย
---------------------------------------------------------------------
change condition for password in registration
แก้ให้การสมัครจะต้องมีรหัสความยาวมากกว่า 8
ref
https://simpleisbetterthancomplex.com/tips/2016/08/04/django-tip-9-password-change-form.html

วันอาทิตย์ที่ 11 มิถุนายน พ.ศ. 2560

scammerlist : commit เพิ่มเติม

styling navbar,about
แก้ไขการแสดงหน้าเว็บให้ปกติโดยการเปลี่ยนชื่อ class ในไฟล์ html

show all report in user page
แสดงทุก report (แสดงเหมือน comment ในเว็บกระทู้ แต่ไม่ได้แสดงวันที่) ในหน้า scammer คนนั้นๆ
โดยใช้ตัวอย่างจากเว็บ bootsnip

add login,logout,login to report
เพิ่มระบบล็อคอินเพื่อ report โดยใช้ระบบของ django authentication
เพิ่มฟังก์ชั่น login เพื่อใช้ในการ login และย้อนกลับไปหน้าที่แล้วด้วยคำสั่ง 
next = request.POST.get('next', '/')
return HttpResponseRedirect(next)
เพิ่ม logout เมื่อล็อกเอาท์เสร็จจะไปกลับไปที่หน้า index และ 
เงื่อนไขใน report ว่าถ้าล็อคอินแล้วถึงจะ report ได้

add username when report
เมื่อ report จะขึ้นชื่อผู้ report ตาม username ที่ login

login to add scammer
ต้องล็อคอินก่อนเพื่อเพิ่มคนโกง
เพื่มเงื่อนไขในหน้า addscammer ว่าถ้าเป็น user.is_authenticate จะสามารถเห็น form เพื่อเพิ่มได้

complete registration
ทำระบบสมัครสมาชิก

add confirm password to register,can't leave blankspace in registration
เพิ่มเงื่อนไขตอนสมัครสมาชิก

  • ยืนยันรหัส (ใส่รหัส 2 ช่องให้ตรงกัน)
  • ไม่สามารถใส่ช่องว่างตอนสมัครได้

เข้าไปดู webapp ที่

https://gentle-springs-97441.herokuapp.com/

วันศุกร์ที่ 26 พฤษภาคม พ.ศ. 2560

app scammerlist : แก้ไข ul list ของหน้าแรก


  • เปลี่ยนแปลงในส่วนของ HTML ให้แสดงเป็น listgroup แทน ul (list) 
    • ให้แสดงเป็นรูปแบบ 6 แถวแล้วขึ้นคอลัมน์ใหม่
  • เพิ่มเลขจำนวนคนใน catalog

การเปลี่ยนแปลงโค้ด

หลังจากเปลี่ยนแล้ว



https://github.com/sovernut/scammerlist/tree/linux

วันอังคารที่ 2 พฤษภาคม พ.ศ. 2560

ลองใช้งาน Heroku ที่เป็น PaaS

สำหรับการนำ App ที่สร้างใน django ไป deploy ลงบน Heroku (Platform as a service) นั้น
จะต้องมีขั้นตอนเตรียมการ pack ให้เขารู้ก่อนว่า app ของเราต้องการใช้อะไรบ้าง


  • ทำการสมัครสมาชิกเว็บ Heroku
  • ติดตั้ง HerokuCLI สามารถเข้าไปดูได้ที่ Heroku
  • ติดตั้ง Virtual Environment เพื่อให้ไม่มีปัญหา เช่น projectA ใช้ django 1.8 projectB ใช้ django 1.10 กรณีติดตั้ง virtualenv จะรันได้ไม่มีปัญหา
  • พิมพ์คำสั่ง เพื่อใช้งาน virtualenv ในโฟลเดอร์ project เรา
    • source venv/bin/activate
  • ทำตามขั้นตอนไป  จนถึงขั้นตอน Build your app จะต้องติดตั้ง gunicorn เพิ่ม
  • จากนั้นทำตามขั้นตอน นี้ แต่ยังไม่ต้อง git push
  • เพราะว่ายังไม่ได้ตั้ง runtime ว่าจะให้ใช้ python version ไหน
  • เข้าไปที่โฟลเดอร์ project เรา สร้างไฟล์ runtime.txt พิมพ์ python-3.6.1 ลงไปแล้ว save
    • จากนั้นก็ commit อีกครั้ง ว่าเปลี่ยน runtime แล้ว
  • ตั้ง path ของ static โดยเข้าไปดูที่ reference 1 และ 3 แล้ว commit อีกรอบว่าตั้ง path แล้ว
    • ref 1 เข้าไปใน project/settings.py และเพิ่มบรรทัดข้างล่างลงไป
    • PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__)) STATIC_ROOT = os.path.join(PROJECT_ROOT, 'staticfiles') STATIC_URL = '/static/' # Extra places for collectstatic to find static files. STATICFILES_DIRS = ( os.path.join(PROJECT_ROOT, 'static'), )
  • เข้าไปใน settings.py เพื่อเพิ่ม allow_host ตามที่ url ที่เขาให้มา
    • หรือ อาจจะลอง push ไปก่อน จะขึ้น Disallow host at ...
    • จากนั้นเข้าไปแก้ใน settings.py เช่น
    • ALLOWED_HOSTS = ['gentle-springs-97441.herokuapp.com'] 
  •  จากนั้น push แล้วก็น่าจะใช้งานได้เลย
reference
  1. https://simpleisbetterthancomplex.com/tutorial/2016/08/09/how-to-deploy-django-applications-on-heroku.html
  2. https://devcenter.heroku.com/articles/deploying-python
  3.  http://stackoverflow.com/questions/12800862/how-to-make-django-serve-static-files-with-gunicorn
  4. http://stackoverflow.com/questions/40667519/why-is-django-throwing-error-disallowedhost-at

หรือ อีกวิธีคือให้ heroku connect ไปที่ github ของเรา



สามารถเข้าไปดู app ได้ที่
https://github.com/sovernut/scammerlist/commits/linux

Webapp:
https://gentle-springs-97441.herokuapp.com/





วันจันทร์ที่ 1 พฤษภาคม พ.ศ. 2560

การใช้ template inheritence ใน Django

การใช้ template inheritence คือการสืบทอดเทมเพลต เพื่อให้ไม่ต้องเขียนโค้ดหน้าเว็บๆซ้ำๆ
เราจะมีหน้าหลักอันเดียว (base.html or parent) ภายในนั้นจะมีตัวแปร
หน้าที่สืบทอด (children) จะสามารถเปลี่ยนแปลงตัวแปรนั้นๆได้


เช่น base.html (Parent)

มีตัวแปรคือ
block header
block maincontent
block table_id
block table

ไฟล์ Children เช่น index.html

มีการใส่ข้อมูลตรงส่วนของ block maincontent คือ จะนำเอาข้อมูลในกล่องนี้ไปแสดงโดยมี
เทมเพลต base.html เป็นหลัก
ส่วนตัวแปรที่ไม่ได้ถูกแทนที่จะไม่แสดง

สรุปก็คือสามารถประหยัดเวลาในการเขียนโค้ดหน้าเว็บซ้ำเดิม หรือ รูปแบบเดียวกันครับ

Slide

วันพุธที่ 26 เมษายน พ.ศ. 2560

TDD Tut 7 : การทดสอบ Layout


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
def test_layout_and_styling(self):
        # Edith goes to the home page
        self.browser.get(self.live_server_url)
        self.browser.set_window_size(1024, 768)

        # She notices the input box is nicely centered
        inputbox = self.browser.find_element_by_id('id_new_item')
        #inputbox.send_keys('testing\n')
        self.assertAlmostEqual(
            inputbox.location['x'] + inputbox.size['width'] / 2,
            512,
            delta=6
        )
บรรทัดที่ 4 จะทำการเปิดBrowser ด้วยขนาด 1024 ,768(ยาว, สูง)
หากล่อง inputbox และทำการเช็คว่า ตำแหน่งของ inputbox อยู่ที่ 512 ( คลาดเคลื่อนได้ 6 ) รึเปล่า

โดยส่วนใหญ่ใน Tutorial นี้จะกล่าวถึงการนำ template มาประกอบกัน หรือ Inheritence
จะมีไฟล์ base.html เป็นตัวหลักที่ home.html และ list.html  นำ template มาใช้แต่เปลี่ยนแปลงเนื้อหาข้างใน เช่น header , formaction header

การใช้ CSS Framework Boostrap ขั้นตอนคือ
โหลดไฟล์ boostrap มาจากเว็บไซต์จากนั้นแตกไฟล์เข้าโฟลเดอร์ static ภายในโฟลเดอร์ app (lists)
ทำการแก้ไขไฟล์ base.html เพื่อให้มี stylesheet เป็น boostrap.min.css

<link href="/static/bootstrap/css/bootstrap.min.css" rel="stylesheet">


เปลี่ยนจาก LiveServerTestCase เป็น StaticLiveServerTestCase เพื่อให้ใช้งานไฟล์ static (เช่น css ) ได้ด้วย


RECAP : 
ไม่ควรใช้ test ในการ test ขนาดและตำแหน่งของ layout
แต่ควร test ว่า css และไฟล์ static ใช้งานได้จริง 


วันพฤหัสบดีที่ 13 เมษายน พ.ศ. 2560

App ที่ทำ

Webapp ที่รวมชื่อคนโกงการซื้อ-ขาย ผ่านอินเทอร์เน็ต โดยผู้ใช้สามารถเพิ่มชื่อได้

Link : https://github.com/sovernut/scammerlist/tree/linux

วันพฤหัสบดีที่ 23 มีนาคม พ.ศ. 2560

ทำการทดสอบ WebApp ด้วยวิธี Test-Driven Development

Test-Driven Development 

เป็นการเขียน โค้ดเพื่อทดสอบการทำงานของโค้ด
เพื่อเราจะได้ไม่ต้องทดสอบการทำงานเอง


ซึ่งสามารถตรวจสอบแบบ 


  • user point of view ( functional tests ) หรือ อาจจะเรียกว่า  user story คือ เมื่อผู้ใช้กดปุ่มนี้พิมพ์อย่างงี้จะได้ผลลัพท์อย่างงี้ไหม
  • programmer point of view  ( unit tests ) เป็นการทดสอบ ฟังก์ชั่น เมธอด ใน class ภายในโปรแกรม

ขั้นตอนการทำ test-driven development


  1. เริ่มให้ทดสอบด้วย functional tests
  2. เมื่อไม่ผ่านให้ทำการใช้ unit test เพื่อทดสอบการทำงานของโค้ด
  3. หากไม่ผ่าน unit test ให้ทำการแก้ไข unit test จนกว่าจะผ่าน
  4. รัน functional tests อีกครั้ง

การ Test นั้นจะใช้คำว่า
assert เพื่อทำการเปรียบเทียบค่า 2 ค่า

Unit Test เช่น
[ ตัวอย่างในบทที่ 3 ]

การทำงานของ django


  1. มี HTTP request เข้ามาสำหรับ url นั้นๆ
  2. Django ตัดสินใจว่าใช้ view ไหนกับ request ที่เข้ามา (resolve)
  3. view จะประมวลผล request และ ส่ง HTTP Response กลับไป ( เช่น หน้าเว็บhtml )

from django.core.urlresolvers import resolve
from django.test import TestCase
from lists.views import home_page #1

class HomePageTest(TestCase):

    def test_root_url_resolves_to_home_page_view(self):
        found = resolve('/')  #2
        self.assertEqual(found.func, home_page)  #3
จะเป็นการเช็คว่า เมื่อเราให้ django ตัดสินใจ (resolve) url ที่เป็น '/' (คือหน้าแรกของเว็บเราเลย)
มันจะเรียกฟังก์ชั่นทที่ชื่อ home_page ไหม


Red/Green/Refactor and Triangulation(โครงข่ายสามเหลี่ยม?)

มีขั้นตอนดังนี้ 
  • ทำการเขียนโค้ดให้เกิดการ fails ( เรียกว่า Red )
  • ทำการเขียนโค้ดสั้นๆที่ทำให้ pass test ( เรียกว่า Green ) เขียนโค่ดแบบให้ผ่านพอไม่จำเป็นต้องดี
  • ทำการ Refactor เพื่อให้โค้ดนั้นทำงานได้ ( เขียนโค้ดให้ดี )

[ link ] http://chimera.labs.oreilly.com/books/1234000000754/index.html

วันพุธที่ 1 มีนาคม พ.ศ. 2560

Account#5: Import CSV

urls.py

เพิ่ม url ของการ import csv

views.py

ฟังก์ชั่นอัพโหลดไฟล์
ตรง file = request.FILES['file'] ชื่อ file จะต้องเหมือนใน forms.py
คำสั่ง codecs.iterdecode เพื่อ decode จากไฟล์ที่เป็น bytes ให้เป็น text ที่สามารถอ่านได้ กรณีไม่ใส่ iterdecode จะขึ้น error
iterator should return strings, not bytes (did you open the file in text mode?)
เรียกใช้ฟังก์ชั่น overwrite_transaction เพื่อแก้ไข ข้อมูล transaction ใน account และเขียนทับลงไปใหม่


newfile forms.py


upload.html

ใน tag form จะต้องมีส่วน enctype="multipart/form-data" และ method="post" เพื่อให้ส่งข้อมูลไปได้

สร้างปุ่ม import csv
หน้าตาประมาณนี้

วันศุกร์ที่ 24 กุมภาพันธ์ พ.ศ. 2560

Account#4 : export csv

urls.py
 
เพิ่ม url สำหรับ export_csv

views.py
ทำการกำหนด content_type เป็น csv (กรณีเอาออก ก็ใช้งานได้เหมือนกัน)
filename เป็นการกำหนดชื่อไฟล์ที่จะเซฟ
ใช้ DictWriter ในการเขียน csvfile

สร้างปุ่ม Export CSV

Account#3 : ใช้ CSS และสร้างหน้า homepage

CSS คือ ภาษาที่ใช้ตกแต่ง HTML ของเรา โดยสามารถเพิ่ม background , สี , กรอบ ,ปรับความกว้าง , ปรับ margin , padding

การใช้ css ใน django 

1.สร้างไฟล์ style.css ใน Accountant\account(folder app)\static\account


วันจันทร์ที่ 20 กุมภาพันธ์ พ.ศ. 2560

Account#2 : เพิ่ม - ลบ Account

เพิ่ม Account

views.py

ใช้คำสั่ง request.POST ในการรับข้อมูลจาก กล่องข้อความทีึ่ชื่อ account_name
หากเกิด error จะเข้า except
หากไม่เกิด error จะเช็คว่าเป็น Alphabet รึเปล่า
ถ้าใช่ก็เพิ่ม Account และ save

ลบ Account


views.py

ใช้คำสั่ง request.POST ในการรับข้อมูลจาก กล่องข้อความทีึ่ชื่อ account_id
หากเกิด error จะเข้า except เพื่อตั้งค่าให้ error_msg และส่ง (error_msg) ไปยัง index.html
หากไม่ error จะทำการลบ Account ตาม account_id ที่อ่านมาได้

วันศุกร์ที่ 10 กุมภาพันธ์ พ.ศ. 2560

Account#1 : สมัคร pythonanywhere และสร้าง webapp บัญชีรายรับ-จ่าย

สมัครเว็บ pythonanywhere

และทำการสร้าง web app



สร้าง app 'account' หรือ บัญชีรายรับ-รายจ่าย



สร้าง model
มี
Account > account_name ชื่อบัญชี , total จำนวนเงินคงเหลือ
Transaction โดยให้ 1 บัญชีมีได้หลาย account โดยใช้คำสั่ง ForeignKey



สร้าง function ใน views
indexview แสดงหน้าเลือกบัญชี
detailview แสดงรายละเอียดบัญชี รายรับ-จ่าย วันที่ และ เพิ่มรายการ



กำหนด url สำหรับการเรียกหน้าเว็บ

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

ใช้ตารางในการแสดงคำถามและตัวเลือก


เพิ่ม url สำหรับหน้า เพิ่มคำถาม และ หน้าเพิ่มคำถาม (เซฟข้อมูลเข้า database)

เพิ่มฟังก์ชั่น add เพื่อแสดงหน้าเพิ่มคำถาม
เพิ่มฟังก์ชั่น adddb สำหรับ เพิ่มคำถามเข้า database


การเพิ่มคำถาม



เพิ่มหน้าเพื่มคำถามสำหรับผู้ใช้

เพิ่มหน้าคำถามสำหรับผู้ใช้งานทั่วไป
ตอนแรกจะต้องแก้ไขไฟล์ ursl.py เพื่อให้ลิงก์ไปยัง ฟังก์ชั่นใหม่ที่เราสร้าง คือ add และ adddb

ฟังก์ชั่นใหม่ที่สร้าง 
add ทำการ render หน้า page ที่ไว้เพิ่มคำถาม
adddb ทำการเพิ่มคำถาม ( เช็คคำถามว่าเขียนไหม + choice มากกว่า 1 ไหม) และ แสดง page ว่า เพิ่มคำถามแล้ว
หน้า add.html สำหรับ แสดงหน้าเพิ่มคำถาม
หน้า adddb สำหรับแสดงว่าเพิ่มคำถามไปแล้ว หรือ แสดงเออเร่อหากตรงเงื่อนไข
หน้าเพิ่มคำถาม

เพิ่มคำถามเสร็จแล้ว

หน้าแรกหลังจากเพิ่ม ส่วนเพิ่มคำถามไป

กรณี error (ไม่ได้ใส่คำถาม หรือ choice < 1 หรือ เข้าหน้านี้โดยตรง)
ทดลองโหวตคำถามใหม่

ทดลองโหวตคำถามใหม่


วันอาทิตย์ที่ 29 มกราคม พ.ศ. 2560

ลองใช้ Django #3

Tutorial 4


  • Write simple form
  • use generic views - less code is better

 แก้ไขไฟล์ detail.html ให้เป็นดังนี้ เพื่อทำการสร้างฟอร์มแบบสำหรับตอบแบบสอบถาม
detail.html

  • name="choice"  เมื่อ submit form จะส่ง post data เป็น choice=id
  • action="{% url 'polls:vote' question.id %}" เมื่อกดจะลิงก์ไปที่ url ของหน้า vote 
  • ค่าที่ส่งไปคือ value ซึ่งคือ choice.id
  • ใช้ method="post" เมื่อต้องการเปลี่ยนแปลงข้อมูลใน server (อ้างอิงจาก tutorial)


views.py

  • request.POST['choice'] > return ค่า id ของตัวเลือกที่เลือกอยู่
  • HttpResponseRedirect > simple argument > ใช้ทุกครั้งหลัง POST data
  • reverse > return a string like '/polls/3/results/'
  • render results.html และส่งค่า question ไป

results.html หน้าแสดงผลลัพท์จากการโหวต
ผลลัพธ์ที่ได้


ทำการทำให้โค้ดสั้นลงโดยใช้ GenericViews


ขั้นแรกทำการแก้ไขไฟล์ urls.py โดยเปลี่ยน question_id เป็น pk เพื่อใช้กับ generic view
urls.py
 จากนั้นแก้ไขใน views.py โดยใช้ class สืบทอดจาก ListView, DetailView

DetailView ต้องการตัวแปร pk (ดังนั้นจึงเปลี่ยนใน urls.py ด้านบน จาก question_id ให้เป็น pk)


  • ตัวแปร template_name ไว้กำหนด template ที่ต้องการจะ render
  • ตัวแปร context_object_name ไว้กำหนดให้เหมือนชื่อตัวแปรในไฟล์ index.html ที่ต้องกำหนดเองเพราะว่า โดยปกติแล้ว DetailView จะทำการ generate context name อัติโนมัติซึ่งในที่นี้จะ generate เป็น question_list แต่ว่าใน index.html เป็นชื่อ lastest_question_list จึงต้องเปลี่ยนให้สอดคล้องกัน
  • model เป็นตัวกำหนดว่าจะให้แสดงข้อมูลของ object ไหน


views.py




commit เพิ่มเติม : เพื่ม userstory, bookmark

>>  add userstory ทำการเพิ่ม userstory ใน functional tests >>  add bookmark for user เพิ่มระบบ Bookmark โดยการสร้าง model ขึ...