ผลต่างระหว่างรุ่นของ "01204223/flask-backend-db"

จาก Theory Wiki
ไปยังการนำทาง ไปยังการค้นหา
แถว 4: แถว 4:
  
 
== โมเดล ==
 
== โมเดล ==
 +
: ''ส่วนนี้ใช้ gemini เขียนให้''
 +
 +
ในบริบทของการพัฒนาซอฟต์แวร์ (Software Development) โดยเฉพาะในส่วนของ Backend หรือ Web Application คำว่า '''"โมเดล" (Model)''' คือส่วนประกอบที่ทำหน้าที่เป็น '''ตัวแทนของโครงสร้างข้อมูลและกฎเกณฑ์ทางธุรกิจ (Business Logic)''' ที่เกี่ยวข้องกับข้อมูลนั้นๆ
 +
 +
เพื่อให้เข้าใจง่ายที่สุด: โมเดลคือ '''"พิมพ์เขียว" (Blueprint)''' ที่บอกโปรแกรมว่าข้อมูลของเราหน้าตาเป็นอย่างไร และจะคุยกับฐานข้อมูล (Database) อย่างไร
 +
 +
=== หน้าที่หลักของ Model ===
 +
 +
Model ทำหน้าที่เป็น '''ตัวกลาง''' ระหว่างโค้ดของโปรแกรม (Application Code) กับ ฐานข้อมูล (Database) โดยมีหน้าที่หลัก 3 ประการ:
 +
 +
* '''กำหนดโครงสร้าง (Structure Definition):''' บอกว่าข้อมูลชุดนี้มีช่องข้อมูล (Fields/Columns) อะไรบ้าง และเป็นชนิดใด (เช่น ข้อความ, ตัวเลข, วันที่)
 +
* '''จัดการข้อมูล (Data Manipulation):''' ใช้สำหรับ ดึง (Read), เพิ่ม (Create), แก้ไข (Update), และ ลบ (Delete) ข้อมูล หรือที่เรียกว่า CRUD
 +
* '''ตรวจสอบความถูกต้อง (Validation):''' ตรวจสอบว่าข้อมูลที่จะบันทึกลงฐานข้อมูลนั้นถูกต้องตามกฎหรือไม่ (เช่น อีเมลต้องมีเครื่องหมาย @)
 +
 +
=== แนวคิด ORM (Object-Relational Mapping) ===
 +
 +
ในการเขียนโปรแกรมสมัยใหม่ เรามักใช้เทคนิคที่เรียกว่า '''ORM''' ผ่าน Model ซึ่งช่วยให้โปรแกรมเมอร์ไม่ต้องเขียนคำสั่ง SQL (ภาษาฐานข้อมูล) ที่ซับซ้อนโดยตรง แต่จะเขียนเป็น "Code" แทน
 +
 +
* '''Class (ในโค้ด):''' เปรียบเสมือน '''ตาราง (Table)''' ในฐานข้อมูล
 +
* '''Object/Instance (ตัวแปร):''' เปรียบเสมือน '''แถว (Row)''' ของข้อมูล 1 รายการ
 +
* '''Attribute (ตัวแปรในคลาส):''' เปรียบเสมือน '''คอลัมน์ (Column)'''
 +
 +
=== ตัวอย่างโค้ด (SQLAlchemy) ===
 +
 +
สมมติว่าเราต้องการเก็บข้อมูล '''"ผู้ใช้งาน" (User)''' โดยใช้ SQLAlchemy แบบดั้งเดิม (Declarative Base)
 +
 +
==== การนิยามโมเดล (Model Definition) ====
 +
 +
เราจะสร้างคลาสเพื่อเป็นตัวแทนตารางในฐานข้อมูล
 +
 +
<syntaxhighlight lang="python">
 +
class User(Base):
 +
    # กำหนดโครงสร้างข้อมูล (Columns)
 +
    id = Column(Integer, primary_key=True)
 +
    name = Column(String(100))
 +
    email = Column(String(100), unique=True)
 +
    age = Column(Integer)
 +
 +
    # กฎทางธุรกิจ (Business Logic)
 +
    def is_adult(self):
 +
        return self.age >= 18
 +
</syntaxhighlight>
 +
 +
ในการใช้งานเราสามารถสั่ง
 +
 +
user.is_adult()
 +
 +
ได้โดยตรง
  
 
== Code เริ่มต้นของ project ==
 
== Code เริ่มต้นของ project ==

รุ่นแก้ไขเมื่อ 20:06, 21 มกราคม 2569

หน้านี้เป็นส่วนหนึ่งของ 01204223

เราจะแก้ส่วน backend ให้ทำงานกับ database    แทนที่เราจะเขียน SQL ตรง ๆ เราจะให้ไลบรารีที่เรียกว่า ORM (Object Relational Mapper) ที่ทำให้เราเขียน-อ่านกับข้อมูลในฐานข้อมูลผ่านทาง object

โมเดล

ส่วนนี้ใช้ gemini เขียนให้

ในบริบทของการพัฒนาซอฟต์แวร์ (Software Development) โดยเฉพาะในส่วนของ Backend หรือ Web Application คำว่า "โมเดล" (Model) คือส่วนประกอบที่ทำหน้าที่เป็น ตัวแทนของโครงสร้างข้อมูลและกฎเกณฑ์ทางธุรกิจ (Business Logic) ที่เกี่ยวข้องกับข้อมูลนั้นๆ

เพื่อให้เข้าใจง่ายที่สุด: โมเดลคือ "พิมพ์เขียว" (Blueprint) ที่บอกโปรแกรมว่าข้อมูลของเราหน้าตาเป็นอย่างไร และจะคุยกับฐานข้อมูล (Database) อย่างไร

หน้าที่หลักของ Model

Model ทำหน้าที่เป็น ตัวกลาง ระหว่างโค้ดของโปรแกรม (Application Code) กับ ฐานข้อมูล (Database) โดยมีหน้าที่หลัก 3 ประการ:

  • กำหนดโครงสร้าง (Structure Definition): บอกว่าข้อมูลชุดนี้มีช่องข้อมูล (Fields/Columns) อะไรบ้าง และเป็นชนิดใด (เช่น ข้อความ, ตัวเลข, วันที่)
  • จัดการข้อมูล (Data Manipulation): ใช้สำหรับ ดึง (Read), เพิ่ม (Create), แก้ไข (Update), และ ลบ (Delete) ข้อมูล หรือที่เรียกว่า CRUD
  • ตรวจสอบความถูกต้อง (Validation): ตรวจสอบว่าข้อมูลที่จะบันทึกลงฐานข้อมูลนั้นถูกต้องตามกฎหรือไม่ (เช่น อีเมลต้องมีเครื่องหมาย @)

แนวคิด ORM (Object-Relational Mapping)

ในการเขียนโปรแกรมสมัยใหม่ เรามักใช้เทคนิคที่เรียกว่า ORM ผ่าน Model ซึ่งช่วยให้โปรแกรมเมอร์ไม่ต้องเขียนคำสั่ง SQL (ภาษาฐานข้อมูล) ที่ซับซ้อนโดยตรง แต่จะเขียนเป็น "Code" แทน

  • Class (ในโค้ด): เปรียบเสมือน ตาราง (Table) ในฐานข้อมูล
  • Object/Instance (ตัวแปร): เปรียบเสมือน แถว (Row) ของข้อมูล 1 รายการ
  • Attribute (ตัวแปรในคลาส): เปรียบเสมือน คอลัมน์ (Column)

ตัวอย่างโค้ด (SQLAlchemy)

สมมติว่าเราต้องการเก็บข้อมูล "ผู้ใช้งาน" (User) โดยใช้ SQLAlchemy แบบดั้งเดิม (Declarative Base)

การนิยามโมเดล (Model Definition)

เราจะสร้างคลาสเพื่อเป็นตัวแทนตารางในฐานข้อมูล

class User(Base):
    # กำหนดโครงสร้างข้อมูล (Columns)
    id = Column(Integer, primary_key=True)
    name = Column(String(100))
    email = Column(String(100), unique=True)
    age = Column(Integer)

    # กฎทางธุรกิจ (Business Logic)
    def is_adult(self):
        return self.age >= 18

ในการใช้งานเราสามารถสั่ง

user.is_adult()

ได้โดยตรง

Code เริ่มต้นของ project

เพื่อความสะดวกเราจะเริ่มต้นจากโค้ดตัวอย่างที่รวบรวมมาแล้ว โดย clone จาก https://github.com/jittat/01204223-flask-react-todo-68

หมายเหตุ โค้ดของเก่ามีผิดพลาดในส่วนของ python backend ตอนที่สั่ง getattr(data,'done',False) จริง ๆ แล้วต้องสั่ง data.get('done', False) เพราะว่า data เป็น dict ไม่ใช่ object     ใน repo นี้แก้ไขแล้ว

เราจะแยกไดเร็กทอรีภายในเป็น backend และ frontend ให้ไปติดตั้งไลบรารีของทั้งสองส่วนดังนี้

Backend

เข้าไปใน backend (ถ้าเป็น windows อย่าลืมใช้ cmd อย่าใช้ powershell)

cd backend

เราจะสร้าง virtual environment และติดตั้งไลบรารี ขั้นแรกสร้าง virtual environment ก่อน

python -m venv venv

แล้ว activate ถ้าเป็น linux/mac เรียก

./venv/bin/activate

ถ้าเป็น windows เรียก

venv\Scripts\activate.bat

เมื่อ activate venv แล้ว ให้เรียก pip เพื่อติดตั้งไลบรารี     เราได้รวบรวมรายกายไลบรารีไว้ในไฟล์ requirements.txt แล้ว ดังนั้นเราจะสั่ง

pip install -r requirements.txt

เพื่อติดตั้งได้เลย ถ้าติดตั้งเรียบร้อยทดลองเรียก flask backend ได้

ขั้นแรก ถ้าเป็น linux/mac ให้เรียก

export FLASK_APP=main.py

ถ้าเป็น windows เรียก

set FLASK_APP=main.py

แล้วเรียก

flask run --debug

Frontend

เปิดอีก terminal หนึ่ง แล้วเรียก

cd frontend

เรียก npm เพื่อติดตั้งไลบรารี

npm install

แล้วเรียก

npm run dev

เพื่อเปิดเซิร์ฟเวอร์ของ frontend react

ระบบฐานข้อมูล

เพื่อความง่าย ในตอนแรกเราจะใช้ระบบฐานข้อมูล sqlite ซึ่งเป็น database system ที่เก็บข้อมูลในไฟล์ และมากับ Python แล้ว เมื่อเราทำเสร็จ เราจะย้ายไปทดลองกับ MySQL หรือ dbms ตัวอื่นที่นิสิตได้เคยติดตั้งตอนเรียนวิชา database

การติดตั้งไลบรารี SQLAlchemy และ SQLAlchemy-Flask

เราจะใช้ SQLAlchemy และ Flask-SQLAlchemy โดยจะต้องติดตั้งไลบรารีเพิ่มเติม ให้เข้าไปในส่วน backend และ activate virtual environment ก่อน จากนั้นสั่ง

pip install Flask-SQLAlchemy

เมื่อติดตั้งเรียบร้อยแล้ว เราจะอัพเดทไฟล์ requirements.txt เพื่อให้รวมไลบรารีเหล่านี้ด้วย    ถ้าเราลองสั่ง

pip freeze

เราจะได้รายการของไลบรารีทั้งหมดที่เราติดตั้งผ่าน pip เราจะเก็บข้อมูลดังกล่าวลงใน requirements.txt โดยสั่ง (เป็นการทำ redirection)

pip freeze > requirements.txt

การเก็บรายการไลบรารีแบบนี้จะมีประโยชน์เมื่อเราต้องการรันระบบของเราที่เครื่องอื่นนอกเหนือจากเครื่องที่เราใช้พัฒนาเอง (และจำเป็นตอนสร้าง container image ตอนที่เราเรียน DevOp ต่อไปด้วย)

โมเดลแรก

เราจะแก้ไข main.py โดยเริ่มจากการ import ไลบรารีที่จำเป็นที่หัวโปรแกรม

from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.orm import DeclarativeBase
from sqlalchemy import Integer, String
from sqlalchemy.orm import Mapped, mapped_column

ในการใช้งาน SQLAlchemy ใน Flask นั้นเราจะต้อง init ไลบรารีก่อน รวมทั้งตั้งค่าเกี่ยวกับฐานข้อมูลที่เราจะใช้ ให้เพิ่มโค้ดต่อไปนี้หลังบรรทัด app = Flask(__name__) และ CORS(app)

ส่วนแรกเป็นการตั้งค่าการเชื่อมต่อฐานข้อมูล ถ้าเราจะเปลี่ยนไปใช้ระบบฐานข้อมูลอื่น เราจะแก้ไขตรงนี้

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///todos.db'

จากนั้นจะสร้างตัวแปร db ที่จะเป็นจุดที่เราเรียกไลบรารีทั้งหมด โดยต้องมีการผูกเข้ากับ Flask app รวมทั้งมีการระบุด้วยว่าในการสร้างโมเดลทั้งหมดจะใช้อะไรเป็น base class (ในที่นี้เราใช้คลาส Base ที่เป็น DeclarativeBase อีกที

class Base(DeclarativeBase):
  pass

db = SQLAlchemy(app, model_class=Base)

ความสัมพันธ์ระหว่างโมเดล (โมเดล Comment)

Migration

แสดงผลบน React