⏱️ ~12 นาที

โปรเจกต์ Fullstack แรกของคุณ

รวม Python + Database + หน้าเว็บเป็นแอปสมบูรณ์ พร้อมแนวทางต่อยอด

🎉 ยินดีด้วย! คุณเกือบจะเป็น Fullstack Developer แล้ว

ตอนนี้คุณมีทักษะครบทุกชั้น:

  • ✅ Python พื้นฐาน
  • ✅ Backend API ด้วย FastAPI
  • ✅ Database ด้วย SQL/SQLite
  • ✅ Frontend พื้นฐาน (HTML/CSS/JS)

บทสุดท้ายนี้ เราจะ ประกอบร่าง เป็นแอปเดียว

แอปตัวอย่าง: "ร้านค้ามินิมอล"

แอปที่:

  • แสดงรายการสินค้า (จาก database)
  • เพิ่มสินค้าใหม่
  • ลบสินค้า

โครงสร้างโปรเจกต์

my-shop/
├── venv/                ← virtual env (อย่าอัป Git)
├── main.py              ← Backend (FastAPI)
├── shop.db              ← database (สร้างอัตโนมัติ)
└── static/
    ├── index.html       ← หน้าเว็บ
    ├── style.css
    └── app.js

1. Backend (main.py)

import sqlite3
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from pydantic import BaseModel

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_methods=["*"],
    allow_headers=["*"],
)

class Product(BaseModel):
    name: str
    price: float

def get_db():
    conn = sqlite3.connect("shop.db")
    conn.row_factory = sqlite3.Row
    return conn

@app.on_event("startup")
def startup():
    conn = get_db()
    conn.execute("""
        CREATE TABLE IF NOT EXISTS products (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            name TEXT NOT NULL,
            price REAL
        )
    """)
    conn.commit()
    conn.close()

@app.get("/api/products")
def list_products():
    conn = get_db()
    rows = conn.execute("SELECT * FROM products").fetchall()
    conn.close()
    return [dict(r) for r in rows]

@app.post("/api/products")
def create_product(product: Product):
    conn = get_db()
    cursor = conn.execute(
        "INSERT INTO products (name, price) VALUES (?, ?)",
        (product.name, product.price)
    )
    conn.commit()
    new_id = cursor.lastrowid
    conn.close()
    return {"id": new_id, "name": product.name, "price": product.price}

@app.delete("/api/products/{product_id}")
def delete_product(product_id: int):
    conn = get_db()
    conn.execute("DELETE FROM products WHERE id = ?", (product_id,))
    conn.commit()
    conn.close()
    return {"message": "ลบแล้ว"}

# เสิร์ฟหน้าเว็บจากโฟลเดอร์ static
app.mount("/", StaticFiles(directory="static", html=True), name="static")

2. Frontend

static/index.html:

<!DOCTYPE html>
<html lang="th">
  <head>
    <meta charset="UTF-8" />
    <title>ร้านค้ามินิมอล</title>
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <h1>🛒 ร้านค้ามินิมอล</h1>

    <form id="add-form">
      <input name="name" placeholder="ชื่อสินค้า" required />
      <input name="price" type="number" placeholder="ราคา" required />
      <button>เพิ่ม</button>
    </form>

    <ul id="list"></ul>

    <script src="app.js"></script>
  </body>
</html>

static/style.css:

body {
  font-family: sans-serif;
  max-width: 500px;
  margin: 40px auto;
  background: #f5f5f5;
}
h1 { color: #2563eb; }
input, button {
  padding: 8px;
  margin: 4px 2px;
  border-radius: 6px;
  border: 1px solid #ccc;
}
button {
  background: #2563eb;
  color: white;
  cursor: pointer;
}
li {
  background: white;
  padding: 12px;
  border-radius: 8px;
  margin: 8px 0;
  list-style: none;
  display: flex;
  justify-content: space-between;
}

static/app.js:

const API = "/api/products";

async function loadProducts() {
  const res = await fetch(API);
  const products = await res.json();

  const list = document.getElementById("list");
  list.innerHTML = "";
  for (const p of products) {
    const li = document.createElement("li");
    li.innerHTML = `<span>${p.name}${p.price} บาท</span>`;

    const btn = document.createElement("button");
    btn.textContent = "ลบ";
    btn.onclick = async () => {
      await fetch(`${API}/${p.id}`, { method: "DELETE" });
      loadProducts();
    };
    li.appendChild(btn);
    list.appendChild(li);
  }
}

document.getElementById("add-form").addEventListener("submit", async (e) => {
  e.preventDefault();
  const form = e.target;
  await fetch(API, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      name: form.name.value,
      price: Number(form.price.value),
    }),
  });
  form.reset();
  loadProducts();
});

loadProducts();

3. รัน

# ติดตั้ง (ครั้งแรก)
python -m venv venv
source venv/bin/activate         # Windows: venv\Scripts\activate
pip install fastapi "uvicorn[standard]"

# รัน
uvicorn main:app --reload

เปิด http://localhost:8000 — ลองเพิ่ม/ลบสินค้า แล้วรีเฟรชดู ข้อมูล อยู่ครบ! 🎉

💡 สังเกตว่าเรา mount static ที่ / ทำให้หน้าเว็บและ API อยู่ ที่เดียวกัน จึงเรียก API ด้วยแค่ /api/products (ไม่ต้องใส่โดเมน)

ทำไมต้องเขียนโปรเจกต์จริง?

  • ฝึก เชื่อม ความรู้ทุกชิ้นเข้าด้วยกัน
  • เจอปัญหาจริง → เรียนรู้ลึก
  • สร้าง พอร์ตโฟลิโอ ให้ผู้จ้างเห็น

💡 อย่า copy ทั้งดุ้น พิมพ์เอง แก้เอง พังเอง แก้เอง — นั่นคือวิธีเรียนรู้จริง

ไอเดียโปรเจกต์ต่อยอด

  1. To-do List — เพิ่ม/ทำเครื่องหมายเสร็จ/ลด งาน
  2. บันทึกการเงิน — รายรับ-รายจ่าย สรุปยอด
  3. API สภาพอากาศ — ดึงข้อมูลจาก API สาธารณะ
  4. บล็อก — โพสต์บทความ + ความคิดเห็น
  5. line bot — ทำบอทตอบข้อความ

บันไดการเติบโตต่อไป

ขั้นเรียนเพิ่ม
Python ลึกขึ้นOOP, decorator, async/await
Backend ลึกAuthentication (JWT), testing (pytest)
Database ลึกPostgreSQL, SQLAlchemy (ORM)
Frontend ทันสมัยReact (เรียนเพิ่มจากสาย JS)
Data / AIpandas, numpy, scikit-learn
DevOpsDocker, Deploy (Railway/Render/Fly.io)

Deploy ขึ้นเน็ตจริง

  • Backend (FastAPI): Railway, Render, Fly.io
  • Database: Supabase (PostgreSQL ฟรี)
  • Frontend: ฝังใน Backend ก็ได้ หรือแยกไป Vercel

ข้อความสุดท้าย

คุณเริ่มจาก 0 ตอนนี้คุณสร้างแอป Fullstack ได้แล้ว — นี่เป็นความสำเร็จใหญ่!

จำไว้:

  • 🌱 เรียนรู้ไม่มีที่สิ้นสุด — ทุกคนยังเรียนทุกวัน
  • 🔁 ลงมือทำ สำคัญกว่าอ่านอย่างเดียว
  • 🧠 เจอ error = โอกาสเรียนรู้ ไม่ใช่ความล้มเหลว
  • 💪 อดทน — สายนี้ต้องใช้เวลา แต่คุ้มทุกวินาที

ขอให้สนุกกับการเดินทางในโลกของนักพัฒนา คุณทำได้! 🚀🎉

อ่านจบแล้ว? ทำเครื่องหมายว่าเสร็จเพื่อบันทึกความคืบหน้า

🧠

แบบทดสอบ

ตอบให้ครบแล้วกด “ตรวจคำตอบ” เพื่อเช็คความเข้าใจ

  1. 1. สถาปัตยกรรม Fullstack ของสาย Python ประกอบด้วยชั้นใด?

  2. 2. วิธีที่หน้าเว็บสื่อสารกับ FastAPI คือ?

  3. 3. หลังเรียนจบ สิ่งที่ควรทำต่อคือ?

กำลังโหลด…