Thursday, October 29, 2020

ฝึกเขียน web ด้วย python ใช้ django กับ database sqlite

ผมเพิ่งเรียนเขียนโปรแกรม python ทาง online ก่อนหน้านี้ไม่เคยเขียนเลย แล้วเขาให้ทำการบ้านส่ง โดย requirement ประมาณว่า โรงพยาบาลแห่งหนึ่ง อยากเช็คได้ว่าคนไข้เคยลงทะเบียนไว้หรือยัง สิ่งที่ต้องทำคือ

1.หน้าลงทะเบียน - ก็ต้องทำฟอร์ม submit ข้อมูล insert เข้า db sqlite

2.หน้าเช็คว่าเคยมี ID นี้หรือยัง - มีฟอร์มให้กรอก ID แล้วไป search ใน sqlite ถ้าเจอข้อมูลก็แสดงออกมา


ก่อนเริ่มเขียน

1.ลง python ในนี้ใช้ python 2.7 เพราะผมเรียนคอร์สเก่าที่สอนมาหลายปีแล้ว ผมลงไว้ใน C:\python27

2.ลง python เสร็จ จะ run pip ได้ ก็ run คำสั่งนี้ต่อ: pip install virtualenvwrapper

3.ลง django ผมลงไว้ใน C:\Python27\Django-1.8.19 จะได้หาง่าย

4.ลง sqlite เลือก sqlite-tools-win32-x86-3330000.zip ผมลงไว้ที่ C:\sqlite มีไฟล์ exe อยู่ 3 ไฟล์เอง

5.ลง PyCharm เลือกตัว Community ใช้ฟรี เป็น studio ช่วยให้เขียน python มีสีสันขึ้น

ผมเขียนบน Windows ไม่จำเป็นต้องใช้ Mac หรือ Ubuntu

หน้าตา pycharm

ลงมือเขียน

เริ่มสร้าง app ด้วยทำสั่ง

C:\Python27\Django-1.8.19\med\>py manage.py startapp client

client คือชื่อ app ที่ผมตั้ง (จริงๆควรใช้ชื่อ patient แต่ตั้งไปแล้วก็แล้วกันไป^^)

settings.py

INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'client', # เพิ่มชื่อ app เราตรงนี้
)

ข้อความหลัง # ข้อความ คือ comment ตัดออกได้

โจทย์บอกให้หน้า home อยู่ที่ http://domainเรา/commoninfo ก็ต้องไปแก้ไฟล์ urls.py ดังนี้

หน้า register อยู่ที่ http://domainเรา/commoninfo/add

หน้า search อยู่ที่ http://domainเรา/commoninfo/fetch

urls.py

from django.conf.urls import patterns, include, url
from client import views #อันนี้ import เพิ่ม
from django.contrib import admin

urlpatterns = [
url(
r'^$/', 'client.views.index', name='index'), #ถ้าไม่ import views ด้านบน เขียนแบบนี้
url(r'^commoninfo/$', views.index, name='home'), #ถ้า import views แล้ว เขียนแบบนี้
url(r'^commoninfo/fetch/$', views.fetch, name='fetch'),
url(r'^commoninfo/add/$', views.add, name='add'),
url(r'^admin/', include(admin.site.urls)),
]

พอเปิด http://domainเรา/commoninfo มันจะไปหาไฟล์ index ก็ต้องไปเพิ่มใน views.py ว่าหน้า index จะแสดงอะไร

views.py

from django.shortcuts import render
from client.models import UserInfo
# ตรงนี้ import เพิ่ม เพื่อให้รู้จัก object UserInfo
from django.utils import timezone
# import เพิ่ม เพื่อให้ใช้ฟังก์ชั่นเกี่ยวกับเวลาได้

def index(request):
context = {
'patient_num': len(UserInfo.objects.all())
# ส่งตัวแปร patient_num = จำนวนคนไข้ทั้งหมดที่มี
}
return render(request, 'index.html', context)

หน้า index ไม่มีอะไร แค่ให้เปิดไฟล์ index.html แต่พิเศษตรงมีการส่งตัวแปรผ่าน context ด้วย

ภายใน context ก็ประกอบด้วย 'ชื่อตัวแปร' : ค่าที่จะส่ง ถ้ามีหลายตัวก็ใส่ comma คั่น

แล้วต้องไปสร้างไฟล์ index.html ต่อ

views.py (ต่อ)

def add(request):
if request.POST:
username = request.POST.get('username', '')
email = request.POST.get('email', '')
password = request.POST.get('password', '')
firstName = request.POST.get('firstName', '')
lastName = request.POST.get('lastName', '')
uniqueID = request.POST.get('uniqueID', '')
dateOfBirth = request.POST.get('dateOfBirth', '')
if uniqueID != "":
UserInfo(username=username, email=email, password=password,
firstName=firstName, lastName=lastName, uniqueID=uniqueID,
dateOfBirth=dateOfBirth).save()
result = 'successfully added!!'
else:
result = ''
context = {'today': timezone.now().strftime('%Y-%m-%dT%H:%M:%S'), 'result': result}
return render(request, 'add.html', context)

1 def คือ 1 หน้า หน้านี้คือเปิดมาจาก http://domainเรา/commoninfo/add แล้วต้องทำอะไรบ้าง

เริ่มต้นเป็นการเช็กค่าว่ามีการโพสต์มาไหม แล้วก็รับค่าที่โพสต์ เอาไป insert ลง db แค่ใช้ UserInfo(ชื่อฟิลด์=ค่า).save() แค่นี้เสร็จ

ส่งผลลัพธ์คือ result เข้าไปใน context แล้วส่ง context ไปให้ไฟล์ add.html

ส่วน today ส่งไปเล่นๆ เอาไว้ให้ตั้ง default ให้ฟิลด์วันที่ในหน้าฟอร์มลงทะเบียน

ต้องไปสร้างไฟล์ add.html ต่อ

views.py (ต่อ)

def fetch(request):
uniqueID = request.POST.get('uniqueID', '')
# รับค่า uniqueID ที่กรอกมาจากฟอร์ม
if request.POST: # เช็คว่ามีการโฟสต์มาหรือเปล่า
result = UserInfo.objects.filter(
uniqueID=uniqueID) # filter คือการ where ใน db
else:
result =
'[]'
if len(result) > 0: # เช็คว่ามีผลลัพธ์ไหม ตรงนี้ผมเขียนมั่วๆเอา น่าจะมีวิธีที่ดีกว่านี้
user = result[
0]
else:
user =
'[]'
context = {'user': user, 'uniqueID': uniqueID} # return ข้อมุล user และ uniqueID
return render(request, 'fetch.html', context)

นี่คือหน้า search หลังจากเปิด http://domainเรา/commoninfo/fetch ก็จะไปเปิดไฟล์ fetch.html โดยส่ง context ไปเหมือนกัน

ต้องไปสร้างไฟล์ fetch.html ต่อ

models.py

from django.db import models

class UserInfo(models.Model):
username = models.CharField(max_length=100)
email = models.CharField(max_length=200)
password = models.CharField(max_length=100)
firstName = models.CharField(max_length=100)
lastName = models.CharField(max_length=100)
uniqueID = models.CharField(max_length=100)
dateOfBirth = models.DateTimeField(max_length=100)

ไฟล์นี้เป็นตัวบอก sqlite ว่าให้สร้าง table ชื่อ UserInfo โดยมีฟิลด์ดังต่อไปนี้

คำสั่งให้สร้าง db คือ

C:\Python27\Django-1.8.19\med\>py manage.py makemigrations

คำสั่งให้ run web server เพื่อให้เราเปิดเว็บได้คือ

C:\Python27\Django-1.8.19\med\>py manage.py runserver


index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AB Hospital</title>
</head>
<body>
<p />
Number of patients: {{ patient_num }}
<!- เอาตัวแปร patient_num จาก context มาแสดง -->
<p />

<a href="/commoninfo">Home</a> |
<a href="/commoninfo/add">Register</a> |
<a href="/commoninfo/fetch">Check</a>

</body>
</html>

หน้าแรกไม่มีอะไร ใส่แค่ลิ้งค์ กับเอาจำนวน record ใน db มาโชว์

add.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Register</title>
</head>
<body>
{{ result }}
<form method="post" action=".">
{% csrf_token %}
Username: <input type="text" name="username" /><br/>
Email: <input type="text" name="email" /><br/>
Password: <input type="text" name="password" /><br/>
Re-type: <input type="text" name="retype" /><br/>
First name: <input type="text" name="firstName" /><br/>
Last name: <input type="text" name="lastName" /><br/>
Unique ID: <input type="text" name="uniqueID" /><br/>
Date of Birth: <input type="text" name="dateOfBirth" value="{{ today }}" /><br/>

<input type="submit" value="REGISTER" />

</form>

<p />

<a href="/commoninfo">Home</a> |
<a href="/commoninfo/add">Register</a> |
<a href="/commoninfo/fetch">Check</a>

</body>
</html>

เป็นหน้าฟอร์มลงทะเบียน มีรับค่า today จาก context มาเป็นค่า default ในช่อง Date Of Birth ด้วย

fetch.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Check</title>
</head>
<body>

<form method="post" action=".">
{% csrf_token %}

UniqueID: <input type="text" name="uniqueID" /><br />

{% if user.uniqueID %}
<h1>User Info</h1>
User's Name: {{ user.firstName }} {{ user.lastName }} <br />
Unique ID: {{ user.uniqueID }}<br />
Dob: {{ user.dateOfBirth }}<br />
{% endif %}

<input type="submit" value="SUBMIT" />
</form>
<p />

<a href="/commoninfo">Home</a> |
<a href="/commoninfo/add">Register</a> |
<a href="/commoninfo/fetch">Check</a>

</body>
</html>

หน้า search มีช่องกรอกค่า Unique ID เพื่อ search 

ตรง action="." คือกดโพสต์แล้วมาหน้าตัวเอง

หลังจากไป search ใน db ตามคำสั่งใน views.py แล้ว ก็มีการเช็ก if ค่ามีค่า user.uniqueID มาหรือเปล่า คือถ้า search เจอ ให้แสดงข้อความที่อยู่ในช่วง

{% if xxx %} กับ {% endif %}

จบข่าว!

ถ้าติดปัญหาอะไร ให้ search google ไม่ต้องถามผม เพราะผมก็เพิ่งหัดเหมือนกัน ^^