1.1 ทำความรู้จักกับ Python และการติดตั้ง
1 ชั่วโมง
Python Basics
📌 ทำไมต้อง Python?
- ง่ายต่อการเรียนรู้: Syntax ที่อ่านง่ายคล้ายภาษาอังกฤษ
- ใช้งานได้หลากหลาย: Web, Data Science, AI, Automation
- Community ใหญ่: Library เยอะ ช่วยแก้ปัญหาง่าย
- ตลาดต้องการสูง: งาน Python Developer เยอะมาก
📥 การติดตั้ง Python
- Download Python:
python.org → Download Python 3.12+
- ติดตั้ง VS Code:
code.visualstudio.com
- ติดตั้ง Extension: Python, Pylance
- ตรวจสอบการติดตั้ง:
# เปิด Terminal/Command Prompt
python --version
# ผลลัพธ์: Python 3.12.x
# หรือ
python3 --version
🔧 Virtual Environment
Virtual Environment คือ "กล่องแยก" สำหรับแต่ละโปรเจค เพื่อไม่ให้ Library ปะปนกัน
# สร้าง Virtual Environment
python -m venv myenv
# เปิดใช้งาน (Windows)
myenv\Scripts\activate
# เปิดใช้งาน (Mac/Linux)
source myenv/bin/activate
# เมื่อเปิดแล้วจะเห็น (myenv) หน้า command line
ตัวอย่าง
💡 โปรแกรมแรก: คำนวณค่า BMI
# โปรแกรมคำนวณค่า BMI (Body Mass Index)
print("=== คำนวณค่า BMI ===")
# รับข้อมูลจากผู้ใช้
weight = float(input("น้ำหนัก (kg): "))
height = float(input("ส่วนสูง (m): "))
# คำนวณ BMI
bmi = weight / (height ** 2)
# แสดงผล
print(f"ค่า BMI ของคุณ: {bmi:.2f}")
# ประเมินผล
if bmi < 18.5:
print("ผอมเกินไป")
elif bmi < 25:
print("น้ำหนักปกติ")
elif bmi < 30:
print("น้ำหนักเกิน")
else:
print("อ้วน")
ทดลองรัน: น้ำหนัก 70 kg, ส่วนสูง 1.75 m → BMI = 22.86 (น้ำหนักปกติ)
1.2 Python Basics
2 ชั่วโมง
Core Concepts
📦 ตัวแปรและชนิดข้อมูล (Variables & Data Types)
1. String (ข้อความ)
# สร้างตัวแปร String
name = "สมชาย"
company = 'บริษัท ABC จำกัด'
address = """123 ถนนสุขุมวิท
กรุงเทพมหานคร 10110"""
# การต่อ String
fullname = "คุณ" + name # "คุณสมชาย"
# f-string (แนะนำ)
message = f"สวัสดีครับ {name} จาก {company}"
# Methods ที่ใช้บ่อย
print(name.upper()) # "สมชาย"
print(name.lower()) # "สมชาย"
print(len(name)) # 5 (จำนวนตัวอักษร)
2. Numbers (ตัวเลข)
# Integer (จำนวนเต็ม)
age = 25
salary = 50000
# Float (ทศนิยม)
height = 1.75
price = 99.99
# การคำนวณ
total = salary * 12 # 600000
bonus = salary * 0.1 # 5000.0
tax = (salary - 60000) * 0.05 # ภาษี
# ฟังก์ชันทางคณิตศาสตร์
import math
print(math.sqrt(16)) # 4.0
print(math.ceil(4.2)) # 5
print(math.floor(4.8)) # 4
3. List (รายการ)
# สร้าง List
fruits = ["แอปเปิล", "กล้วย", "ส้ม"]
numbers = [1, 2, 3, 4, 5]
mixed = ["ข้อความ", 100, 3.14, True]
# เข้าถึงข้อมูล (Index เริ่มที่ 0)
print(fruits[0]) # "แอปเปิล"
print(fruits[-1]) # "ส้ม" (นับจากท้าย)
# เพิ่มข้อมูล
fruits.append("องุ่น") # เพิ่มท้าย
fruits.insert(0, "มะม่วง") # เพิ่มตำแหน่งที่ 0
# ลบข้อมูล
fruits.remove("กล้วย") # ลบตามค่า
fruits.pop() # ลบตัวสุดท้าย
# Loop ผ่าน List
for fruit in fruits:
print(f"ผลไม้: {fruit}")
# List Comprehension (เทคนิคขั้นสูง)
squares = [x**2 for x in range(1, 6)] # [1, 4, 9, 16, 25]
4. Dictionary (พจนานุกรม)
# สร้าง Dictionary (คีย์-ค่า)
person = {
"name": "สมชาย",
"age": 25,
"city": "กรุงเทพ",
"salary": 50000
}
# เข้าถึงข้อมูล
print(person["name"]) # "สมชาย"
print(person.get("age")) # 25
# เพิ่ม/แก้ไขข้อมูล
person["email"] = "somchai@email.com"
person["age"] = 26
# ลบข้อมูล
del person["city"]
# Loop ผ่าน Dictionary
for key, value in person.items():
print(f"{key}: {value}")
# ตัวอย่างการใช้งานจริง: สินค้า
product = {
"id": "P001",
"name": "โน้ตบุ๊ค",
"price": 25000,
"stock": 10
}
🔄 Control Flow (การควบคุมโปรแกรม)
1. If-Elif-Else
# ตัวอย่าง: เกรด
score = 85
if score >= 80:
grade = "A"
elif score >= 70:
grade = "B"
elif score >= 60:
grade = "C"
elif score >= 50:
grade = "D"
else:
grade = "F"
print(f"คะแนน {score} ได้เกรด {grade}")
# Multiple Conditions
age = 25
has_license = True
if age >= 18 and has_license:
print("สามารถขับรถได้")
elif age >= 18 and not has_license:
print("ต้องมีใบขับขี่ก่อน")
else:
print("ยังเด็กเกินไป")
2. Loops (การวนซ้ำ)
# For Loop - วนตามจำนวนที่กำหนด
for i in range(5):
print(f"รอบที่ {i+1}")
# For Loop - วนผ่าน List
employees = ["สมชาย", "สมหญิง", "สมศรี"]
for emp in employees:
print(f"พนักงาน: {emp}")
# While Loop - วนจนกว่าเงื่อนไขจะเป็นเท็จ
count = 0
while count < 5:
print(f"Count: {count}")
count += 1
# Break & Continue
for i in range(10):
if i == 3:
continue # ข้ามรอบนี้
if i == 7:
break # หยุด loop
print(i)
Workshop
🔨 Workshop: ระบบคำนวณเงินเดือนพนักงาน
โจทย์: สร้างโปรแกรมคำนวณเงินเดือนพนักงานที่มี:
- เงินเดือนพื้นฐาน
- โบนัส 10% (ถ้าทำงานครบ 1 ปี)
- ค่า OT 150 บาท/ชั่วโมง
- หัก ประกันสังคม 5%
# ระบบคำนวณเงินเดือน
print("=== ระบบคำนวณเงินเดือนพนักงาน ===\n")
# รับข้อมูล
name = input("ชื่อพนักงาน: ")
basic_salary = float(input("เงินเดือนพื้นฐาน: "))
years = int(input("อายุงาน (ปี): "))
ot_hours = float(input("ชั่วโมง OT: "))
# คำนวณ
bonus = 0
if years >= 1:
bonus = basic_salary * 0.10
ot_pay = ot_hours * 150
gross_salary = basic_salary + bonus + ot_pay
social_security = gross_salary * 0.05
net_salary = gross_salary - social_security
# แสดงผล
print(f"\n{'='*40}")
print(f"สรุปเงินเดือนของ {name}")
print(f"{'='*40}")
print(f"เงินเดือนพื้นฐาน: {basic_salary:>10,.2f} บาท")
print(f"โบนัส: {bonus:>10,.2f} บาท")
print(f"ค่า OT: {ot_pay:>10,.2f} บาท")
print(f"{'='*40}")
print(f"รวมรายได้: {gross_salary:>10,.2f} บาท")
print(f"หัก ประกันสังคม: {social_security:>10,.2f} บาท")
print(f"{'='*40}")
print(f"เงินสุทธิ: {net_salary:>10,.2f} บาท")
ผลลัพธ์ตัวอย่าง:
ชื่อพนักงาน: สมชาย
เงินเดือนพื้นฐาน: 30000
อายุงาน (ปี): 2
ชั่วโมง OT: 10
========================================
สรุปเงินเดือนของ สมชาย
========================================
เงินเดือนพื้นฐาน: 30,000.00 บาท
โบนัส: 3,000.00 บาท
ค่า OT: 1,500.00 บาท
========================================
รวมรายได้: 34,500.00 บาท
หัก ประกันสังคม: 1,725.00 บาท
========================================
เงินสุทธิ: 32,775.00 บาท
1.3 Functions & Modules
30 นาที
Code Organization
📝 Functions (ฟังก์ชัน)
ฟังก์ชันคือ "กล่องโค้ด" ที่ทำงานเฉพาะอย่าง สามารถเรียกใช้ซ้ำได้
การสร้างและใช้งาน Function
# Function พื้นฐาน
def greet(name):
"""ฟังก์ชันทักทาย"""
return f"สวัสดี {name}"
# เรียกใช้
message = greet("สมชาย")
print(message) # "สวัสดี สมชาย"
# Function หลายพารามิเตอร์
def calculate_salary(basic, bonus_rate, ot_hours):
"""คำนวณเงินเดือน"""
bonus = basic * bonus_rate
ot_pay = ot_hours * 150
return basic + bonus + ot_pay
# เรียกใช้
total = calculate_salary(30000, 0.1, 10)
print(f"เงินเดือนรวม: {total:,.2f} บาท")
# Function ที่มีค่าเริ่มต้น
def create_employee(name, department="ฝ่ายขาย", salary=25000):
return {
"name": name,
"department": department,
"salary": salary
}
emp1 = create_employee("สมชาย")
emp2 = create_employee("สมหญิง", "ฝ่ายบัญชี", 30000)
# Function Return หลายค่า
def calculate_stats(numbers):
"""คำนวณสถิติพื้นฐาน"""
total = sum(numbers)
avg = total / len(numbers)
maximum = max(numbers)
minimum = min(numbers)
return total, avg, maximum, minimum
# เรียกใช้
data = [10, 20, 30, 40, 50]
sum_val, avg_val, max_val, min_val = calculate_stats(data)
📦 Modules (โมดูล)
Module คือไฟล์ Python ที่เก็บ Functions ไว้ใช้งานร่วมกัน
การสร้างและใช้งาน Module
1. สร้างไฟล์ tax_calculator.py
# tax_calculator.py
"""โมดูลคำนวณภาษี"""
def calculate_vat(amount, rate=0.07):
"""คำนวณภาษีมูลค่าเพิ่ม (VAT)"""
return amount * rate
def calculate_income_tax(income):
"""คำนวณภาษีเงินได้"""
if income <= 150000:
return 0
elif income <= 300000:
return (income - 150000) * 0.05
elif income <= 500000:
return 7500 + (income - 300000) * 0.10
elif income <= 750000:
return 27500 + (income - 500000) * 0.15
else:
return 65000 + (income - 750000) * 0.20
def calculate_social_security(salary):
"""คำนวณประกันสังคม"""
max_salary = 15000
rate = 0.05
base = min(salary, max_salary)
return base * rate
2. ใช้งาน Module ในไฟล์อื่น
# main.py
import tax_calculator
# หรือ
from tax_calculator import calculate_vat, calculate_income_tax
# ใช้งาน
price = 10000
vat = calculate_vat(price)
print(f"ราคา: {price:,.2f} บาท")
print(f"VAT 7%: {vat:,.2f} บาท")
print(f"รวม: {price + vat:,.2f} บาท")
# คำนวณภาษีเงินได้
annual_income = 600000
tax = calculate_income_tax(annual_income)
print(f"\nรายได้ต่อปี: {annual_income:,.2f} บาท")
print(f"ภาษีที่ต้องจ่าย: {tax:,.2f} บาท")
ตัวอย่าง
💡 สร้าง Utility Functions สำหรับคำนวณภาษี
# utils.py - ไฟล์เก็บ Utility Functions
def format_currency(amount):
"""แปลงตัวเลขเป็นรูปแบบเงิน"""
return f"{amount:,.2f} บาท"
def calculate_net_salary(gross_salary, tax_rate=0.05):
"""คำนวณเงินเดือนสุทธิ"""
tax = gross_salary * tax_rate
net = gross_salary - tax
return {
"gross": gross_salary,
"tax": tax,
"net": net
}
def validate_salary(salary):
"""ตรวจสอบความถูกต้องของเงินเดือน"""
if salary < 0:
return False, "เงินเดือนต้องมากกว่า 0"
if salary < 10000:
return False, "เงินเดือนต่ำกว่าขั้นต่ำ"
return True, "OK"
# การใช้งาน
if __name__ == "__main__":
salary = 50000
result = calculate_net_salary(salary)
print(f"เงินเดือนรวม: {format_currency(result['gross'])}")
print(f"หักภาษี: {format_currency(result['tax'])}")
print(f"เงินสุทธิ: {format_currency(result['net'])}")
1.4 Object-Oriented Programming (OOP)
2.5 ชั่วโมง
Advanced
🎯 เป้าหมาย
เข้าใจแนวคิด OOP และสามารถสร้าง Class สำหรับจัดการข้อมูลได้
🏗️ แนวคิด OOP
OOP คือการเขียนโปรแกรมโดยมอง "สิ่งของ" เป็น Object ที่มี:
- Attributes: คุณลักษณะ (เช่น รถมี สี, ยี่ห้อ, ราคา)
- Methods: พฤติกรรม (เช่น รถสามารถ ขับ, เบรก, เติมน้ำมัน)
1. Class และ Object
# Class = แม่พิมพ์ (Blueprint)
class Car:
"""คลาสรถยนต์"""
def __init__(self, brand, color, price):
"""Constructor - กำหนดค่าเริ่มต้น"""
self.brand = brand
self.color = color
self.price = price
self.fuel = 100 # ค่าเริ่มต้น
def drive(self, distance):
"""ขับรถ"""
fuel_needed = distance * 0.1
if self.fuel >= fuel_needed:
self.fuel -= fuel_needed
return f"ขับไป {distance} km เหลือน้ำมัน {self.fuel:.1f}%"
else:
return "น้ำมันไม่พอ!"
def refuel(self):
"""เติมน้ำมัน"""
self.fuel = 100
return "เติมน้ำมันเต็มแล้ว"
def get_info(self):
"""แสดงข้อมูลรถ"""
return f"{self.color} {self.brand} ราคา {self.price:,.0f} บาท"
# Object = สิ่งที่สร้างจาก Class
car1 = Car("Toyota", "แดง", 500000)
car2 = Car("Honda", "ขาว", 600000)
# เรียกใช้ Method
print(car1.get_info())
print(car1.drive(50))
print(car1.refuel())
2. Inheritance (การสืบทอด)
Class ลูกสามารถรับคุณสมบัติจาก Class แม่
# Class แม่
class BankAccount:
"""บัญชีธนาคารทั่วไป"""
def __init__(self, account_no, owner, balance=0):
self.account_no = account_no
self.owner = owner
self.balance = balance
def deposit(self, amount):
"""ฝากเงิน"""
self.balance += amount
return f"ฝาก {amount:,.0f} บาท คงเหลือ {self.balance:,.0f} บาท"
def withdraw(self, amount):
"""ถอนเงิน"""
if amount <= self.balance:
self.balance -= amount
return f"ถอน {amount:,.0f} บาท คงเหลือ {self.balance:,.0f} บาท"
return "เงินไม่พอ!"
def get_balance(self):
"""เช็คยอด"""
return f"ยอดเงินคงเหลือ: {self.balance:,.0f} บาท"
# Class ลูก 1: บัญชีออมทรัพย์
class SavingAccount(BankAccount):
"""บัญชีออมทรัพย์ (มีดอกเบี้ย)"""
def __init__(self, account_no, owner, balance=0, interest_rate=0.015):
super().__init__(account_no, owner, balance)
self.interest_rate = interest_rate
def add_interest(self):
"""เพิ่มดอกเบี้ย"""
interest = self.balance * self.interest_rate
self.balance += interest
return f"ได้ดอกเบี้ย {interest:,.2f} บาท"
# Class ลูก 2: บัญชีกระแสรายวัน
class CurrentAccount(BankAccount):
"""บัญชีกระแสรายวัน (ถอนเกินได้)"""
def __init__(self, account_no, owner, balance=0, overdraft_limit=5000):
super().__init__(account_no, owner, balance)
self.overdraft_limit = overdraft_limit
def withdraw(self, amount):
"""ถอนเงิน (ถอนเกินได้)"""
if amount <= self.balance + self.overdraft_limit:
self.balance -= amount
return f"ถอน {amount:,.0f} บาท คงเหลือ {self.balance:,.0f} บาท"
return f"ไม่สามารถถอนได้ (วงเงิน overdraft: {self.overdraft_limit:,.0f})"
# การใช้งาน
saving = SavingAccount("001", "สมชาย", 10000)
print(saving.deposit(5000))
print(saving.add_interest())
print(saving.get_balance())
current = CurrentAccount("002", "สมหญิง", 1000, overdraft_limit=3000)
print(current.withdraw(3500)) # ถอนเกินได้
print(current.get_balance())
3. Encapsulation (การห่อหุ้ม)
ซ่อนข้อมูลสำคัญ ป้องกันการเข้าถึงโดยตรง
class SecureBankAccount:
"""บัญชีที่มีความปลอดภัย"""
def __init__(self, account_no, owner, pin):
self.account_no = account_no
self.owner = owner
self.__balance = 0 # Private attribute
self.__pin = pin # Private attribute
self.__locked = False # Private attribute
def verify_pin(self, pin):
"""ตรวจสอบ PIN"""
return pin == self.__pin
def deposit(self, amount, pin):
"""ฝากเงิน (ต้องใช้ PIN)"""
if not self.verify_pin(pin):
return "PIN ไม่ถูกต้อง!"
self.__balance += amount
return f"ฝาก {amount:,.0f} บาท สำเร็จ"
def withdraw(self, amount, pin):
"""ถอนเงิน (ต้องใช้ PIN)"""
if self.__locked:
return "บัญชีถูกล็อค! กรุณาติดต่อธนาคาร"
if not self.verify_pin(pin):
return "PIN ไม่ถูกต้อง!"
if amount <= self.__balance:
self.__balance -= amount
return f"ถอน {amount:,.0f} บาท สำเร็จ"
return "เงินไม่พอ!"
def get_balance(self, pin):
"""เช็คยอด (ต้องใช้ PIN)"""
if not self.verify_pin(pin):
return "PIN ไม่ถูกต้อง!"
return f"ยอดเงิน: {self.__balance:,.0f} บาท"
def change_pin(self, old_pin, new_pin):
"""เปลี่ยน PIN"""
if not self.verify_pin(old_pin):
return "PIN เดิมไม่ถูกต้อง!"
self.__pin = new_pin
return "เปลี่ยน PIN สำเร็จ"
# การใช้งาน
account = SecureBankAccount("123", "สมชาย", "1234")
print(account.deposit(10000, "1234"))
print(account.withdraw(3000, "1234"))
print(account.get_balance("1234"))
print(account.withdraw(3000, "9999")) # PIN ผิด
4. Polymorphism (พหุสัณฐาน)
Class ต่างกันสามารถมี Method ชื่อเดียวกันได้ แต่ทำงานต่างกัน
class Dog:
def speak(self):
return "โฮ่ง โฮ่ง!"
class Cat:
def speak(self):
return "เหมียว!"
class Cow:
def speak(self):
return "มอ~"
# Polymorphism ในการใช้งาน
animals = [Dog(), Cat(), Cow()]
for animal in animals:
print(f"{animal.__class__.__name__}: {animal.speak()}")
# ผลลัพธ์:
# Dog: โฮ่ง โฮ่ง!
# Cat: เหมียว!
# Cow: มอ~
Workshop
🔨 Workshop: ระบบจัดการบัญชีธนาคาร
โจทย์: สร้างระบบบัญชีธนาคารที่มี 3 ประเภท
# bank_system.py
from datetime import datetime
class BankAccount:
"""บัญชีธนาคารพื้นฐาน"""
account_count = 0 # Class variable
def __init__(self, owner, initial_balance=0):
BankAccount.account_count += 1
self.account_no = f"ACC{BankAccount.account_count:04d}"
self.owner = owner
self.balance = initial_balance
self.transactions = []
self._add_transaction("เปิดบัญชี", initial_balance)
def _add_transaction(self, type, amount):
"""บันทึกรายการ (Private method)"""
self.transactions.append({
"datetime": datetime.now(),
"type": type,
"amount": amount,
"balance": self.balance
})
def deposit(self, amount):
"""ฝากเงิน"""
if amount <= 0:
return "จำนวนเงินต้องมากกว่า 0"
self.balance += amount
self._add_transaction("ฝาก", amount)
return f"ฝาก {amount:,.0f} บาท สำเร็จ"
def withdraw(self, amount):
"""ถอนเงิน"""
if amount <= 0:
return "จำนวนเงินต้องมากกว่า 0"
if amount > self.balance:
return "เงินในบัญชีไม่พอ"
self.balance -= amount
self._add_transaction("ถอน", amount)
return f"ถอน {amount:,.0f} บาท สำเร็จ"
def get_balance(self):
"""เช็คยอด"""
return f"บัญชี {self.account_no} ({self.owner}): {self.balance:,.0f} บาท"
def print_statement(self):
"""พิมพ์สเตทเม้นท์"""
print(f"\n{'='*60}")
print(f"สเตทเม้นท์บัญชี: {self.account_no}")
print(f"ชื่อบัญชี: {self.owner}")
print(f"{'='*60}")
print(f"{'วันที่/เวลา':<20} {'รายการ':<15} {'จำนวน':>12} {'คงเหลือ':>12}")
print(f"{'-'*60}")
for trans in self.transactions:
dt = trans['datetime'].strftime('%Y-%m-%d %H:%M:%S')
print(f"{dt:<20} {trans['type']:<15} {trans['amount']:>12,.0f} {trans['balance']:>12,.0f}")
print(f"{'='*60}")
print(f"ยอดเงินคงเหลือ: {self.balance:>34,.0f} บาท")
print(f"{'='*60}\n")
class SavingAccount(BankAccount):
"""บัญชีออมทรัพย์"""
def __init__(self, owner, initial_balance=0, interest_rate=1.5):
super().__init__(owner, initial_balance)
self.interest_rate = interest_rate / 100 # แปลงเป็นทศนิยม
def add_interest(self):
"""เพิ่มดอกเบี้ยรายปี"""
interest = self.balance * self.interest_rate
self.balance += interest
self._add_transaction("ดอกเบี้ย", interest)
return f"ได้รับดอกเบี้ย {interest:,.2f} บาท ({self.interest_rate*100}%)"
class CurrentAccount(BankAccount):
"""บัญชีกระแสรายวัน"""
def __init__(self, owner, initial_balance=0, overdraft_limit=5000):
super().__init__(owner, initial_balance)
self.overdraft_limit = overdraft_limit
def withdraw(self, amount):
"""ถอนเงิน (ถอนเกินได้)"""
if amount <= 0:
return "จำนวนเงินต้องมากกว่า 0"
if amount > self.balance + self.overdraft_limit:
return f"ไม่สามารถถอนได้ (วงเงิน overdraft: {self.overdraft_limit:,.0f} บาท)"
self.balance -= amount
self._add_transaction("ถอน", amount)
return f"ถอน {amount:,.0f} บาท สำเร็จ"
def get_overdraft_status(self):
"""ตรวจสอบสถานะ overdraft"""
if self.balance >= 0:
return f"ยอดคงเหลือ: {self.balance:,.0f} บาท (ไม่ใช้ overdraft)"
else:
used = abs(self.balance)
remaining = self.overdraft_limit - used
return f"ใช้ overdraft: {used:,.0f} บาท (คงเหลือ: {remaining:,.0f} บาท)"
class FixedDeposit(BankAccount):
"""บัญชีฝากประจำ"""
def __init__(self, owner, amount, term_months, interest_rate=2.5):
super().__init__(owner, amount)
self.term_months = term_months
self.interest_rate = interest_rate / 100
self.maturity_date = None
self._locked = True
def withdraw(self, amount):
"""ถอนก่อนกำหนด (มีค่าปรับ)"""
if self._locked:
penalty = amount * 0.02 # ปรับ 2%
net_amount = amount - penalty
self.balance -= amount
self._add_transaction(f"ถอนก่อนกำหนด (ปรับ {penalty:,.2f})", amount)
return f"ถอน {net_amount:,.2f} บาท (หักค่าปรับ {penalty:,.2f} บาท)"
return super().withdraw(amount)
def mature(self):
"""ครบกำหนด"""
total_interest = self.balance * self.interest_rate * (self.term_months / 12)
self.balance += total_interest
self._locked = False
self._add_transaction("ครบกำหนด", total_interest)
return f"ครบกำหนด! ได้รับดอกเบี้ย {total_interest:,.2f} บาท"
# ทดสอบระบบ
if __name__ == "__main__":
# สร้างบัญชีออมทรัพย์
saving = SavingAccount("สมชาย", 10000, interest_rate=1.5)
print(saving.deposit(5000))
print(saving.withdraw(2000))
print(saving.add_interest())
saving.print_statement()
# สร้างบัญชีกระแสรายวัน
current = CurrentAccount("สมหญิง", 1000, overdraft_limit=5000)
print(current.withdraw(3000)) # ถอนเกิน
print(current.get_overdraft_status())
current.print_statement()
# สร้างบัญชีฝากประจำ
fixed = FixedDeposit("สมศรี", 50000, term_months=12, interest_rate=2.5)
print(fixed.mature())
fixed.print_statement()
1.5 Exception Handling (การจัดการข้อผิดพลาด)
1 ชั่วโมง
Error Management
🚨 ทำไมต้องจัดการ Error?
- ป้องกันโปรแกรม Crash
- แสดงข้อความที่เป็นมิตรกับผู้ใช้
- Log ข้อผิดพลาดเพื่อ Debug
- ทำให้โปรแกรมทำงานต่อได้แม้เจอปัญหา
1. Try-Except พื้นฐาน
# ตัวอย่างที่ผิดพลาด (ไม่มี Error Handling)
number = int(input("กรอกตัวเลข: ")) # ถ้าใส่ตัวอักษร → Error!
# แก้ไขด้วย Try-Except
try:
number = int(input("กรอกตัวเลข: "))
result = 100 / number
print(f"ผลลัพธ์: {result}")
except ValueError:
print("❌ กรุณากรอกตัวเลขเท่านั้น!")
except ZeroDivisionError:
print("❌ ไม่สามารถหารด้วย 0 ได้!")
except Exception as e:
print(f"❌ เกิดข้อผิดพลาด: {e}")
2. Try-Except-Else-Finally
def read_file(filename):
"""อ่านไฟล์พร้อมจัดการ Error"""
try:
file = open(filename, 'r', encoding='utf-8')
content = file.read()
except FileNotFoundError:
print(f"❌ ไม่พบไฟล์: {filename}")
return None
except PermissionError:
print(f"❌ ไม่มีสิทธิ์เข้าถึงไฟล์: {filename}")
return None
else:
# ทำงานถ้าไม่มี Error
print(f"✅ อ่านไฟล์สำเร็จ")
return content
finally:
# ทำงานเสมอ ไม่ว่าจะมี Error หรือไม่
try:
file.close()
print("ปิดไฟล์แล้ว")
except:
pass
# การใช้งาน
data = read_file("data.txt")
if data:
print(data)
3. Raise Exception (โยน Error เอง)
def withdraw(balance, amount):
"""ถอนเงิน"""
if amount <= 0:
raise ValueError("จำนวนเงินต้องมากกว่า 0")
if amount > balance:
raise ValueError(f"เงินไม่พอ! (มี {balance:,.0f} บาท)")
return balance - amount
# การใช้งาน
try:
new_balance = withdraw(1000, 1500)
print(f"ถอนเงินสำเร็จ คงเหลือ {new_balance:,.0f} บาท")
except ValueError as e:
print(f"❌ {e}")
4. Custom Exception
# สร้าง Exception เอง
class InsufficientFundsError(Exception):
"""Error เมื่อเงินไม่พอ"""
pass
class InvalidAmountError(Exception):
"""Error เมื่อจำนวนเงินไม่ถูกต้อง"""
pass
class BankAccount:
def __init__(self, balance):
self.balance = balance
def withdraw(self, amount):
"""ถอนเงิน"""
if amount <= 0:
raise InvalidAmountError(f"จำนวนเงินไม่ถูกต้อง: {amount}")
if amount > self.balance:
raise InsufficientFundsError(
f"เงินไม่พอ! ต้องการ {amount:,.0f} บาท "
f"แต่มีเพียง {self.balance:,.0f} บาท"
)
self.balance -= amount
return self.balance
# การใช้งาน
account = BankAccount(5000)
try:
account.withdraw(-100)
except InvalidAmountError as e:
print(f"❌ {e}")
try:
account.withdraw(10000)
except InsufficientFundsError as e:
print(f"❌ {e}")
try:
new_balance = account.withdraw(3000)
print(f"✅ ถอนสำเร็จ คงเหลือ {new_balance:,.0f} บาท")
except (InvalidAmountError, InsufficientFundsError) as e:
print(f"❌ {e}")
Workshop
🔨 Workshop: ปรับปรุงระบบธนาคารด้วย Error Handling
# bank_with_error_handling.py
class InvalidAmountError(Exception):
"""จำนวนเงินไม่ถูกต้อง"""
pass
class InsufficientFundsError(Exception):
"""เงินไม่พอ"""
pass
class AccountLockedError(Exception):
"""บัญชีถูกล็อค"""
pass
class BankAccount:
def __init__(self, account_no, owner, balance=0):
self.account_no = account_no
self.owner = owner
self.balance = balance
self.locked = False
self.failed_attempts = 0
def deposit(self, amount):
"""ฝากเงิน"""
try:
if self.locked:
raise AccountLockedError("บัญชีถูกล็อค กรุณาติดต่อธนาคาร")
if amount <= 0:
raise InvalidAmountError("จำนวนเงินต้องมากกว่า 0")
self.balance += amount
return f"✅ ฝาก {amount:,.0f} บาท สำเร็จ คงเหลือ {self.balance:,.0f} บาท"
except (InvalidAmountError, AccountLockedError) as e:
return f"❌ {e}"
def withdraw(self, amount, pin):
"""ถอนเงิน"""
try:
if self.locked:
raise AccountLockedError("บัญชีถูกล็อค กรุณาติดต่อธนาคาร")
# ตรวจสอบ PIN
if not self._verify_pin(pin):
self.failed_attempts += 1
if self.failed_attempts >= 3:
self.locked = True
raise AccountLockedError("PIN ผิด 3 ครั้ง บัญชีถูกล็อคแล้ว!")
raise ValueError(f"PIN ไม่ถูกต้อง! (เหลือ {3-self.failed_attempts} ครั้ง)")
# Reset failed attempts
self.failed_attempts = 0
if amount <= 0:
raise InvalidAmountError("จำนวนเงินต้องมากกว่า 0")
if amount > self.balance:
raise InsufficientFundsError(
f"เงินไม่พอ! ต้องการ {amount:,.0f} บาท "
f"แต่มีเพียง {self.balance:,.0f} บาท"
)
self.balance -= amount
return f"✅ ถอน {amount:,.0f} บาท สำเร็จ คงเหลือ {self.balance:,.0f} บาท"
except (InvalidAmountError, InsufficientFundsError, AccountLockedError, ValueError) as e:
return f"❌ {e}"
def _verify_pin(self, pin):
"""ตรวจสอบ PIN (สมมติ PIN คือ 1234)"""
return pin == "1234"
def transfer(self, to_account, amount, pin):
"""โอนเงิน"""
try:
# ถอนจากบัญชีต้นทาง
result = self.withdraw(amount, pin)
if "❌" in result:
return result
# ฝากเข้าบัญชีปลายทาง
to_account.deposit(amount)
return f"✅ โอน {amount:,.0f} บาท ไปยัง {to_account.account_no} สำเร็จ"
except Exception as e:
return f"❌ การโอนล้มเหลว: {e}"
# ทดสอบ
def test_bank_system():
# สร้างบัญชี
acc1 = BankAccount("001", "สมชาย", 10000)
acc2 = BankAccount("002", "สมหญิง", 5000)
print("=== ทดสอบระบบธนาคาร ===\n")
# Test 1: ฝากเงิน
print("1. ทดสอบฝากเงิน:")
print(acc1.deposit(5000))
print(acc1.deposit(-100)) # Error: จำนวนเงินไม่ถูกต้อง
print()
# Test 2: ถอนเงิน
print("2. ทดสอบถอนเงิน:")
print(acc1.withdraw(3000, "1234")) # สำเร็จ
print(acc1.withdraw(20000, "1234")) # Error: เงินไม่พอ
print()
# Test 3: PIN ผิด
print("3. ทดสอบ PIN ผิด:")
print(acc1.withdraw(1000, "0000")) # PIN ผิด ครั้งที่ 1
print(acc1.withdraw(1000, "1111")) # PIN ผิด ครั้งที่ 2
print(acc1.withdraw(1000, "9999")) # PIN ผิด ครั้งที่ 3 → ล็อคบัญชี
print(acc1.withdraw(1000, "1234")) # บัญชีถูกล็อค
print()
# Test 4: โอนเงิน
print("4. ทดสอบโอนเงิน:")
acc3 = BankAccount("003", "สมศรี", 20000)
print(acc3.transfer(acc2, 5000, "1234"))
print(f"บัญชีต้นทาง ({acc3.account_no}): {acc3.balance:,.0f} บาท")
print(f"บัญชีปลายทาง ({acc2.account_no}): {acc2.balance:,.0f} บาท")
if __name__ == "__main__":
test_bank_system()
📝 Homework - วันที่ 1
โจทย์: สร้างระบบจัดการสินค้าคงคลัง (Inventory System) แบบ OOP
ความต้องการ:
- Class
Product: เก็บข้อมูลสินค้า (รหัส, ชื่อ, ราคา, จำนวน)
- Class
Inventory: จัดการรายการสินค้าทั้งหมด
- ฟีเจอร์: เพิ่ม, ลบ, แก้ไข, ค้นหา สินค้า
- ตรวจสอบ stock ต่ำกว่าที่กำหนด (Low Stock Alert)
- คำนวณมูลค่ารวมของสินค้าคงคลัง
- มี Error Handling ครบทุก function
2.1 HTML Essentials
1.5 ชั่วโมง
Frontend
🌐 ทำความเข้าใจ HTML
HTML (HyperText Markup Language) คือภาษาที่ใช้สร้างโครงสร้างหน้าเว็บ
1. โครงสร้าง HTML5 พื้นฐาน
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>เว็บไซต์แรกของฉัน</title>
</head>
<body>
<h1>สวัสดีครับ</h1>
<p>นี่คือหน้าเว็บแรกของฉัน</p>
</body>
</html>
2. Tags สำคัญที่ต้องรู้
<!-- Headings -->
<h1>หัวข้อใหญ่สุด</h1>
<h2>หัวข้อรอง</h2>
<h3>หัวข้อย่อย</h3>
<!-- Paragraph -->
<p>ข้อความทั่วไป</p>
<!-- Links -->
<a href="https://www.google.com">ไปที่ Google</a>
<!-- Images -->
<img src="image.jpg" alt="รูปภาพ">
<!-- Lists -->
<ul>
<li>รายการที่ 1</li>
<li>รายการที่ 2</li>
</ul>
<ol>
<li>ขั้นตอนที่ 1</li>
<li>ขั้นตอนที่ 2</li>
</ol>
<!-- Division (Container) -->
<div class="container">
<p>เนื้อหาในกล่อง</p>
</div>
<!-- Span (Inline) -->
<p>ข้อความ <span class="highlight">ที่เน้น</span> บางส่วน</p>
3. Forms (ฟอร์มรับข้อมูล)
<form action="/submit" method="POST">
<!-- Text Input -->
<label for="name">ชื่อ:</label>
<input type="text" id="name" name="name" required>
<!-- Email Input -->
<label for="email">อีเมล:</label>
<input type="email" id="email" name="email" required>
<!-- Password -->
<label for="password">รหัสผ่าน:</label>
<input type="password" id="password" name="password">
<!-- Number -->
<label for="age">อายุ:</label>
<input type="number" id="age" name="age" min="1" max="100">
<!-- Select Dropdown -->
<label for="department">แผนก:</label>
<select id="department" name="department">
<option value="sales">ฝ่ายขาย</option>
<option value="it">ฝ่าย IT</option>
<option value="hr">ฝ่ายบุคคล</option>
</select>
<!-- Radio Button -->
<label>เพศ:</label>
<input type="radio" id="male" name="gender" value="male">
<label for="male">ชาย</label>
<input type="radio" id="female" name="gender" value="female">
<label for="female">หญิง</label>
<!-- Checkbox -->
<input type="checkbox" id="agree" name="agree">
<label for="agree">ยอมรับเงื่อนไข</label>
<!-- Textarea -->
<label for="message">ข้อความ:</label>
<textarea id="message" name="message" rows="4"></textarea>
<!-- Submit Button -->
<button type="submit">ส่งข้อมูล</button>
</form>
4. Table (ตาราง)
<table>
<thead>
<tr>
<th>รหัส</th>
<th>ชื่อพนักงาน</th>
<th>แผนก</th>
<th>เงินเดือน</th>
</tr>
</thead>
<tbody>
<tr>
<td>E001</td>
<td>สมชาย</td>
<td>ฝ่ายขาย</td>
<td>30,000</td>
</tr>
<tr>
<td>E002</td>
<td>สมหญิง</td>
<td>ฝ่ายบัญชี</td>
<td>35,000</td>
</tr>
</tbody>
</table>
5. Semantic HTML5
ใช้ Tag ที่บ่งบอกความหมายชัดเจน ช่วย SEO และอ่านง่าย
<header>
<nav>
<ul>
<li><a href="#home">หน้าแรก</a></li>
<li><a href="#about">เกี่ยวกับเรา</a></li>
<li><a href="#contact">ติดต่อเรา</a></li>
</ul>
</nav>
</header>
<main>
<section id="home">
<h1>ยินดีต้อนรับ</h1>
<p>เนื้อหาหลัก</p>
</section>
<article>
<h2>บทความ</h2>
<p>เนื้อหาบทความ</p>
</article>
<aside>
<h3>Sidebar</h3>
<p>เนื้อหาเสริม</p>
</aside>
</main>
<footer>
<p>© 2024 บริษัทของเรา</p>
</footer>
ตัวอย่าง
💡 สร้างฟอร์มลงทะเบียนพนักงาน
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<title>ลงทะเบียนพนักงาน</title>
</head>
<body>
<h1>📝 แบบฟอร์มลงทะเบียนพนักงาน</h1>
<form action="/register" method="POST">
<fieldset>
<legend>ข้อมูลส่วนตัว</legend>
<label for="firstname">ชื่อ: *</label>
<input type="text" id="firstname" name="firstname" required>
<label for="lastname">นามสกุล: *</label>
<input type="text" id="lastname" name="lastname" required>
<label for="email">อีเมล: *</label>
<input type="email" id="email" name="email" required>
<label for="phone">เบอร์โทร:</label>
<input type="tel" id="phone" name="phone" pattern="[0-9]{10}">
<label for="birthdate">วันเกิด:</label>
<input type="date" id="birthdate" name="birthdate">
<label>เพศ:</label>
<input type="radio" id="male" name="gender" value="male">
<label for="male">ชาย</label>
<input type="radio" id="female" name="gender" value="female">
<label for="female">หญิง</label>
</fieldset>
<fieldset>
<legend>ข้อมูลการทำงาน</legend>
<label for="empid">รหัสพนักงาน:</label>
<input type="text" id="empid" name="empid">
<label for="department">แผนก:</label>
<select id="department" name="department">
<option value="">-- เลือกแผนก --</option>
<option value="sales">ฝ่ายขาย</option>
<option value="it">ฝ่าย IT</option>
<option value="hr">ฝ่ายบุคคล</option>
<option value="finance">ฝ่ายการเงิน</option>
</select>
<label for="position">ตำแหน่ง:</label>
<input type="text" id="position" name="position">
<label for="salary">เงินเดือน:</label>
<input type="number" id="salary" name="salary" min="15000">
<label for="startdate">วันที่เริ่มงาน:</label>
<input type="date" id="startdate" name="startdate">
</fieldset>
<button type="submit">ส่งข้อมูล</button>
<button type="reset">ล้างข้อมูล</button>
</form>
</body>
</html>
2.2 CSS Fundamentals
1.5 ชั่วโมง
Styling
🎨 ทำความเข้าใจ CSS
CSS (Cascading Style Sheets) ใช้สำหรับตกแต่งหน้าเว็บให้สวยงาม
1. การเชื่อมต่อ CSS กับ HTML
<!-- 1. Inline CSS -->
<p style="color: red; font-size: 20px;">ข้อความสีแดง</p>
<!-- 2. Internal CSS -->
<head>
<style>
p {
color: blue;
font-size: 16px;
}
</style>
</head>
<!-- 3. External CSS (แนะนำ) -->
<head>
<link rel="stylesheet" href="styles.css">
</head>
2. Selectors (ตัวเลือก)
/* Element Selector */
p {
color: black;
}
/* Class Selector */
.highlight {
background-color: yellow;
}
/* ID Selector */
#header {
font-size: 24px;
}
/* Multiple Selectors */
h1, h2, h3 {
font-family: Arial, sans-serif;
}
/* Descendant Selector */
div p {
margin: 10px;
}
/* Child Selector */
div > p {
padding: 5px;
}
/* Pseudo-classes */
a:hover {
color: red;
}
button:active {
transform: scale(0.95);
}
3. Box Model
.box {
/* Content */
width: 300px;
height: 200px;
/* Padding (ระยะห่างด้านใน) */
padding: 20px;
/* หรือกำหนดแยก */
padding-top: 10px;
padding-right: 15px;
padding-bottom: 10px;
padding-left: 15px;
/* Border (กรอบ) */
border: 2px solid #333;
border-radius: 10px;
/* Margin (ระยะห่างด้านนอก) */
margin: 20px auto;
/* หรือกำหนดแยก */
margin-top: 20px;
margin-right: auto;
margin-bottom: 20px;
margin-left: auto;
}
4. Flexbox (จัดเรียงแบบยืดหยุ่น)
/* Container */
.container {
display: flex;
/* จัดเรียงในแนวนอน (default) */
flex-direction: row;
/* หรือ column สำหรับแนวตั้ง */
/* จัดเรียงแนวนอน */
justify-content: center; /* flex-start, flex-end, space-between, space-around */
/* จัดเรียงแนวตั้ง */
align-items: center; /* flex-start, flex-end, stretch */
/* ให้ขึ้นบรรทัดใหม่ถ้าไม่พอ */
flex-wrap: wrap;
/* ระยะห่างระหว่าง item */
gap: 20px;
}
/* Items */
.item {
flex: 1; /* ขยายเต็มพื้นที่ */
/* หรือ */
flex-grow: 1;
flex-shrink: 1;
flex-basis: auto;
}
5. Grid (จัดเรียงแบบตาราง)
.grid-container {
display: grid;
/* กำหนดจำนวนคอลัมน์ */
grid-template-columns: 1fr 1fr 1fr; /* 3 คอลัมน์เท่ากัน */
/* หรือ */
grid-template-columns: 200px auto 200px;
/* หรือ */
grid-template-columns: repeat(3, 1fr);
/* กำหนดจำนวนแถว */
grid-template-rows: 100px auto 100px;
/* ระยะห่าง */
gap: 20px;
/* หรือกำหนดแยก */
column-gap: 20px;
row-gap: 10px;
}
.grid-item {
/* กำหนดขอบเขต */
grid-column: 1 / 3; /* ครอบคลุม 2 คอลัมน์ */
grid-row: 1 / 2;
}
6. Responsive Design
/* Mobile First Approach */
.container {
width: 100%;
padding: 10px;
}
/* Tablet */
@media (min-width: 768px) {
.container {
width: 750px;
margin: 0 auto;
}
}
/* Desktop */
@media (min-width: 1024px) {
.container {
width: 960px;
}
}
/* Large Desktop */
@media (min-width: 1200px) {
.container {
width: 1140px;
}
}
Workshop
🔨 Workshop: ออกแบบหน้า Login ที่สวยงาม
สร้างหน้า Login ที่มี:
- การ์ดตรงกลางหน้าจอ
- Gradient Background
- Form Validation Styles
- Hover Effects
- Responsive Design
HTML:
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login</title>
<link rel="stylesheet" href="login.css">
</head>
<body>
<div class="container">
<div class="login-card">
<div class="login-header">
<h1>🔐 เข้าสู่ระบบ</h1>
<p>ยินดีต้อนรับกลับมา</p>
</div>
<form class="login-form">
<div class="form-group">
<label for="username">ชื่อผู้ใช้</label>
<input type="text" id="username" placeholder="กรอกชื่อผู้ใช้" required>
</div>
<div class="form-group">
<label for="password">รหัสผ่าน</label>
<input type="password" id="password" placeholder="กรอกรหัสผ่าน" required>
</div>
<div class="form-group checkbox">
<input type="checkbox" id="remember">
<label for="remember">จดจำฉันไว้</label>
</div>
<button type="submit" class="btn-login">เข้าสู่ระบบ</button>
<div class="form-footer">
<a href="#">ลืมรหัสผ่าน?</a>
<a href="#">สร้างบัญชีใหม่</a>
</div>
</form>
</div>
</div>
</body>
</html>
CSS (login.css):
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.container {
width: 100%;
padding: 20px;
}
.login-card {
max-width: 400px;
margin: 0 auto;
background: white;
border-radius: 20px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
overflow: hidden;
}
.login-header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 40px 30px;
text-align: center;
}
.login-header h1 {
font-size: 28px;
margin-bottom: 10px;
}
.login-header p {
opacity: 0.9;
font-size: 14px;
}
.login-form {
padding: 30px;
}
.form-group {
margin-bottom: 20px;
}
.form-group label {
display: block;
margin-bottom: 8px;
color: #333;
font-weight: 500;
}
.form-group input[type="text"],
.form-group input[type="password"] {
width: 100%;
padding: 12px 15px;
border: 2px solid #e1e1e1;
border-radius: 8px;
font-size: 14px;
transition: all 0.3s;
}
.form-group input:focus {
outline: none;
border-color: #667eea;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
}
.form-group.checkbox {
display: flex;
align-items: center;
}
.form-group.checkbox input {
width: auto;
margin-right: 8px;
}
.btn-login {
width: 100%;
padding: 14px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
border-radius: 8px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: transform 0.2s, box-shadow 0.3s;
}
.btn-login:hover {
transform: translateY(-2px);
box-shadow: 0 10px 20px rgba(102, 126, 234, 0.4);
}
.btn-login:active {
transform: translateY(0);
}
.form-footer {
margin-top: 20px;
display: flex;
justify-content: space-between;
font-size: 14px;
}
.form-footer a {
color: #667eea;
text-decoration: none;
}
.form-footer a:hover {
text-decoration: underline;
}
/* Responsive */
@media (max-width: 480px) {
.login-card {
border-radius: 0;
}
.login-header {
padding: 30px 20px;
}
.login-form {
padding: 20px;
}
}
2.4 การเชื่อมต่อ Python กับ HTML/CSS
2 ชั่วโมง
Integration
Template Rendering
# app.py
from http.server import HTTPServer, BaseHTTPRequestHandler
from string import Template
class ProductHandler(BaseHTTPRequestHandler):
def do_GET(self):
# อ่าน Template
with open('template.html', 'r', encoding='utf-8') as f:
template = Template(f.read())
# ข้อมูล
products = [
{"name": "โน้ตบุ๊ค", "price": 25000, "stock": 5},
{"name": "เมาส์", "price": 500, "stock": 20},
{"name": "คีย์บอร์ด", "price": 1200, "stock": 15}
]
# สร้าง HTML สำหรับสินค้า
product_html = ""
for p in products:
product_html += f'''
<tr>
<td>{p['name']}</td>
<td>{p['price']:,} บาท</td>
<td>{p['stock']}</td>
</tr>
'''
# แทนค่าใน Template
html = template.substitute(products=product_html)
self.send_response(200)
self.send_header('Content-type', 'text/html; charset=utf-8')
self.end_headers()
self.wfile.write(html.encode())
template.html:
<!DOCTYPE html>
<html>
<head>
<title>รายการสินค้า</title>
<style>
table { border-collapse: collapse; width: 100%; }
th, td { padding: 10px; text-align: left; border: 1px solid #ddd; }
th { background: #667eea; color: white; }
</style>
</head>
<body>
<h1>รายการสินค้า</h1>
<table>
<thead>
<tr>
<th>สินค้า</th>
<th>ราคา</th>
<th>คงเหลือ</th>
</tr>
</thead>
<tbody>
$products
</tbody>
</table>
</body>
</html>
Workshop
🔨 Project: ระบบแสดงรายการสินค้าพร้อมค้นหา
# product_system.py
from http.server import HTTPServer, BaseHTTPRequestHandler
from urllib.parse import urlparse, parse_qs
import json
products_db = [
{"id": 1, "name": "โน้ตบุ๊ค Dell", "category": "computer", "price": 25000, "stock": 5},
{"id": 2, "name": "เมาส์ Logitech", "category": "accessory", "price": 500, "stock": 20},
{"id": 3, "name": "คีย์บอร์ด Mechanical", "category": "accessory", "price": 1200, "stock": 15},
{"id": 4, "name": "Monitor LG 24\"", "category": "computer", "price": 4500, "stock": 8},
]
class ProductServer(BaseHTTPRequestHandler):
def do_GET(self):
parsed_path = urlparse(self.path)
if parsed_path.path == '/':
self.serve_html()
elif parsed_path.path == '/api/search':
self.search_products(parsed_path.query)
elif parsed_path.path == '/styles.css':
self.serve_css()
def serve_html(self):
html = '''
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<title>ระบบค้นหาสินค้า</title>
<link rel="stylesheet" href="/styles.css">
</head>
<body>
<div class="container">
<h1>🛍️ ระบบค้นหาสินค้า</h1>
<div class="search-box">
<input type="text" id="searchInput" placeholder="ค้นหาสินค้า...">
<select id="categoryFilter">
<option value="">ทุกหมวดหมู่</option>
<option value="computer">คอมพิวเตอร์</option>
<option value="accessory">อุปกรณ์เสริม</option>
</select>
<button onclick="searchProducts()">ค้นหา</button>
</div>
<div id="results"></div>
</div>
<script>
function searchProducts() {
const keyword = document.getElementById('searchInput').value;
const category = document.getElementById('categoryFilter').value;
fetch(`/api/search?keyword=${keyword}&category=${category}`)
.then(res => res.json())
.then(data => {
displayResults(data);
});
}
function displayResults(products) {
const container = document.getElementById('results');
if (products.length === 0) {
container.innerHTML = '<p>ไม่พบสินค้า</p>';
return;
}
let html = '<div class="product-grid">';
products.forEach(p => {
html += `
<div class="product-card">
<h3>${p.name}</h3>
<p class="category">${p.category}</p>
<p class="price">${p.price.toLocaleString()} บาท</p>
<p class="stock">คงเหลือ: ${p.stock} ชิ้น</p>
</div>
`;
});
html += '</div>';
container.innerHTML = html;
}
// Load all products on start
searchProducts();
</script>
</body>
</html>
'''
self.send_response(200)
self.send_header('Content-type', 'text/html; charset=utf-8')
self.end_headers()
self.wfile.write(html.encode())
def search_products(self, query_string):
params = parse_qs(query_string)
keyword = params.get('keyword', [''])[0].lower()
category = params.get('category', [''])[0]
results = products_db
if keyword:
results = [p for p in results if keyword in p['name'].lower()]
if category:
results = [p for p in results if p['category'] == category]
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps(results, ensure_ascii=False).encode())
if __name__ == '__main__':
server = HTTPServer(('localhost', 8000), ProductServer)
print("Server: http://localhost:8000")
server.serve_forever()
3.1 Django Setup & Project Structure
1 ชั่วโมง
โครงสร้าง Django Project
myproject/
├── manage.py # คำสั่งจัดการโปรเจค
├── myproject/ # โฟลเดอร์หลัก
│ ├── __init__.py
│ ├── settings.py # การตั้งค่า
│ ├── urls.py # URL Routing
│ ├── asgi.py
│ └── wsgi.py
สร้าง Django App
# สร้าง App
python manage.py startapp blog
# โครงสร้าง App
blog/
├── __init__.py
├── admin.py # Admin Interface
├── apps.py # App Configuration
├── models.py # Database Models
├── views.py # Views (Logic)
├── urls.py # URL Routing (สร้างเอง)
├── tests.py # Tests
└── migrations/ # Database Migrations
เพิ่ม App ใน Settings
# myproject/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog', # เพิ่ม App ของเรา
]
Demo
💡 สร้าง Blog Project
# 1. สร้าง Project
django-admin startproject blog_project
cd blog_project
# 2. สร้าง App
python manage.py startapp posts
# 3. เพิ่ม App ใน settings.py
# blog_project/settings.py
INSTALLED_APPS = [
...
'posts',
]
# 4. สร้าง View แรก
# posts/views.py
from django.http import HttpResponse
def index(request):
return HttpResponse("สวัสดี! นี่คือ Blog ของฉัน")
# 5. สร้าง URL
# posts/urls.py (สร้างไฟล์ใหม่)
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
]
# 6. เชื่อม URL กับ Project
# blog_project/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('posts.urls')),
]
# 7. รัน Server
python manage.py runserver
3.2 Views & Templates
2 ชั่วโมง
Function-Based Views (FBV)
# posts/views.py
from django.shortcuts import render
from django.http import HttpResponse
def home(request):
"""หน้าแรก"""
return render(request, 'posts/home.html')
def post_list(request):
"""รายการบทความ"""
posts = [
{'title': 'บทความที่ 1', 'content': 'เนื้อหา...'},
{'title': 'บทความที่ 2', 'content': 'เนื้อหา...'},
]
context = {'posts': posts}
return render(request, 'posts/post_list.html', context)
def post_detail(request, post_id):
"""รายละเอียดบทความ"""
# ดึงข้อมูลจาก Database (เรียนในหัวข้อถัดไป)
post = {'id': post_id, 'title': f'บทความที่ {post_id}'}
return render(request, 'posts/detail.html', {'post': post})
Django Template Language (DTL)
<!-- posts/templates/posts/post_list.html -->
<!DOCTYPE html>
<html>
<head>
<title>รายการบทความ</title>
</head>
<body>
<h1>บทความทั้งหมด</h1>
{% if posts %}
{% for post in posts %}
<article>
<h2>{{ post.title }}</h2>
<p>{{ post.content }}</p>
<a href="{% url 'post_detail' post.id %}">อ่านเพิ่มเติม</a>
</article>
{% endfor %}
{% else %}
<p>ยังไม่มีบทความ</p>
{% endif %}
</body>
</html>
Template Inheritance (สืบทอด Template)
<!-- templates/base.html -->
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<title>{% block title %}My Blog{% endblock %}</title>
<style>
body { font-family: Arial; margin: 0; padding: 0; }
nav { background: #333; color: white; padding: 10px; }
.container { padding: 20px; }
</style>
</head>
<body>
<nav>
<a href="{% url 'home' %}">หน้าแรก</a>
<a href="{% url 'post_list' %}">บทความ</a>
</nav>
<div class="container">
{% block content %}
{% endblock %}
</div>
<footer>
<p>© 2024 My Blog</p>
</footer>
</body>
</html>
<!-- posts/templates/posts/home.html -->
{% extends 'base.html' %}
{% block title %}หน้าแรก - My Blog{% endblock %}
{% block content %}
<h1>ยินดีต้อนรับสู่ Blog ของฉัน</h1>
<p>ที่นี่มีบทความดีๆ มากมาย</p>
{% endblock %}
Workshop
🔨 สร้างระบบ CRUD พื้นฐาน (Blog Posts)
สร้างระบบจัดการบทความที่มี:
- แสดงรายการบทความ (List)
- แสดงรายละเอียด (Detail)
- เพิ่มบทความ (Create)
- แก้ไขบทความ (Update)
- ลบบทความ (Delete)
3.3 Models & Database
2 ชั่วโมง
สร้าง Model
# posts/models.py
from django.db import models
from django.contrib.auth.models import User
class Category(models.Model):
"""หมวดหมู่"""
name = models.CharField(max_length=100)
slug = models.SlugField(unique=True)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name_plural = "Categories"
def __str__(self):
return self.name
class Post(models.Model):
"""บทความ"""
STATUS_CHOICES = [
('draft', 'แบบร่าง'),
('published', 'เผยแพร่'),
]
title = models.CharField(max_length=200)
slug = models.SlugField(unique=True)
author = models.ForeignKey(User, on_delete=models.CASCADE)
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True)
content = models.TextField()
status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='draft')
views = models.IntegerField(default=0)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['-created_at']
def __str__(self):
return self.title
class Comment(models.Model):
"""ความคิดเห็น"""
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
author = models.CharField(max_length=100)
email = models.EmailField()
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f'Comment by {self.author} on {self.post}'
Migrations
# สร้าง Migration files
python manage.py makemigrations
# ดู SQL ที่จะรัน
python manage.py sqlmigrate posts 0001
# รัน Migrations
python manage.py migrate
# ดู Migrations ทั้งหมด
python manage.py showmigrations
Workshop
🔨 สร้างฐานข้อมูล E-commerce
# shop/models.py
from django.db import models
class Category(models.Model):
name = models.CharField(max_length=100)
description = models.TextField(blank=True)
def __str__(self):
return self.name
class Product(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE)
name = models.CharField(max_length=200)
sku = models.CharField(max_length=50, unique=True)
description = models.TextField()
price = models.DecimalField(max_digits=10, decimal_places=2)
stock = models.IntegerField(default=0)
image = models.ImageField(upload_to='products/', blank=True)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
class Customer(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
email = models.EmailField(unique=True)
phone = models.CharField(max_length=20)
address = models.TextField()
def __str__(self):
return f"{self.first_name} {self.last_name}"
class Order(models.Model):
STATUS_CHOICES = [
('pending', 'รอดำเนินการ'),
('processing', 'กำลังจัดส่ง'),
('completed', 'สำเร็จ'),
('cancelled', 'ยกเลิก'),
]
customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='pending')
total_amount = models.DecimalField(max_digits=10, decimal_places=2)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"Order #{self.id} by {self.customer}"
class OrderItem(models.Model):
order = models.ForeignKey(Order, on_delete=models.CASCADE, related_name='items')
product = models.ForeignKey(Product, on_delete=models.CASCADE)
quantity = models.IntegerField()
price = models.DecimalField(max_digits=10, decimal_places=2)
def __str__(self):
return f"{self.quantity}x {self.product.name}"
3.5 QuerySet & Database Operations
1 ชั่วโมง
CRUD Operations
# Create
post = Post.objects.create(
title="บทความใหม่",
slug="new-post",
content="เนื้อหา...",
author=request.user
)
# Read (Single)
post = Post.objects.get(id=1)
post = Post.objects.get(slug='new-post')
# Read (Multiple)
posts = Post.objects.all()
published = Post.objects.filter(status='published')
latest = Post.objects.filter(status='published')[:5]
# Update
post = Post.objects.get(id=1)
post.title = "แก้ไขชื่อ"
post.save()
# หรือ
Post.objects.filter(id=1).update(title="แก้ไขชื่อ")
# Delete
post = Post.objects.get(id=1)
post.delete()
# หรือ
Post.objects.filter(id=1).delete()
Filtering & Ordering
# Filter
Post.objects.filter(status='published')
Post.objects.filter(views__gte=100) # views >= 100
Post.objects.filter(title__contains='Django')
Post.objects.filter(created_at__year=2024)
# Exclude
Post.objects.exclude(status='draft')
# Order
Post.objects.order_by('-created_at') # ใหม่สุดก่อน
Post.objects.order_by('title')
# Limit
Post.objects.all()[:10] # 10 รายการแรก
# Count
Post.objects.filter(status='published').count()
# Exists
Post.objects.filter(slug='test').exists()
Practice
🔨 Query ข้อมูลขายดีประจำเดือน
from django.db.models import Sum, Count, Avg
from datetime import datetime, timedelta
# สินค้าขายดีในเดือนนี้
this_month = datetime.now().replace(day=1)
next_month = (this_month + timedelta(days=32)).replace(day=1)
top_products = OrderItem.objects.filter(
order__created_at__gte=this_month,
order__created_at__lt=next_month,
order__status='completed'
).values('product__name').annotate(
total_quantity=Sum('quantity'),
total_revenue=Sum('price')
).order_by('-total_quantity')[:10]
# ยอดขายรวมประจำเดือน
monthly_revenue = Order.objects.filter(
created_at__gte=this_month,
created_at__lt=next_month,
status='completed'
).aggregate(total=Sum('total_amount'))
print(f"ยอดขายเดือนนี้: {monthly_revenue['total']:,.2f} บาท")
4.1 Forms & Validation
1.5 ชั่วโมง
Django Forms
# posts/forms.py
from django import forms
from .models import Post, Comment
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['title', 'slug', 'category', 'content', 'status']
widgets = {
'title': forms.TextInput(attrs={'class': 'form-control'}),
'slug': forms.TextInput(attrs={'class': 'form-control'}),
'content': forms.Textarea(attrs={'class': 'form-control', 'rows': 10}),
}
def clean_title(self):
"""Custom validation"""
title = self.cleaned_data['title']
if len(title) < 10:
raise forms.ValidationError("ชื่อต้องมีอย่างน้อย 10 ตัวอักษร")
return title
class CommentForm(forms.Form):
author = forms.CharField(max_length=100, label="ชื่อ")
email = forms.EmailField(label="อีเมล")
content = forms.CharField(widget=forms.Textarea, label="ความคิดเห็น")
def clean_content(self):
content = self.cleaned_data['content']
if len(content) < 10:
raise forms.ValidationError("ความคิดเห็นสั้นเกินไป")
return content
ใช้งาน Forms ใน Views
# posts/views.py
from django.shortcuts import render, redirect
from .forms import PostForm, CommentForm
from .models import Post
def create_post(request):
if request.method == 'POST':
form = PostForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.save()
return redirect('post_detail', slug=post.slug)
else:
form = PostForm()
return render(request, 'posts/create.html', {'form': form})
def edit_post(request, slug):
post = Post.objects.get(slug=slug)
if request.method == 'POST':
form = PostForm(request.POST, instance=post)
if form.is_valid():
form.save()
return redirect('post_detail', slug=post.slug)
else:
form = PostForm(instance=post)
return render(request, 'posts/edit.html', {'form': form, 'post': post})
ตัวอย่าง
💡 ฟอร์มลงทะเบียนลูกค้า
# forms.py
from django import forms
from .models import Customer
class CustomerRegistrationForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)
confirm_password = forms.CharField(widget=forms.PasswordInput)
class Meta:
model = Customer
fields = ['first_name', 'last_name', 'email', 'phone', 'address']
def clean_email(self):
email = self.cleaned_data['email']
if Customer.objects.filter(email=email).exists():
raise forms.ValidationError("อีเมลนี้ถูกใช้แล้ว")
return email
def clean(self):
cleaned_data = super().clean()
password = cleaned_data.get('password')
confirm = cleaned_data.get('confirm_password')
if password != confirm:
raise forms.ValidationError("รหัสผ่านไม่ตรงกัน")
return cleaned_data
# views.py
def register(request):
if request.method == 'POST':
form = CustomerRegistrationForm(request.POST)
if form.is_valid():
customer = form.save(commit=False)
customer.set_password(form.cleaned_data['password'])
customer.save()
return redirect('login')
else:
form = CustomerRegistrationForm()
return render(request, 'register.html', {'form': form})