📘 BÀI 4: FLASK + SQLITE (CẬP NHẬT & XÓA DỮ LIỆU – CRUD HOÀN CHỈNH)
🎯 Mục tiêu bài học
- Hiểu mô hình CRUD (Create – Read – Update – Delete).
- Hoàn thiện ứng dụng Flask quản lý học sinh.
- Tạo giao diện chỉnh sửa và xóa học sinh trực tiếp từ bảng dữ liệu.
🧩 1. Cấu trúc thư mục dự án
flask_crud/
├─ app.py
├─ students.db
└─ templates/
├─ index.html
├─ list.html
└─ edit.html
⚙️ 2. File app.py
import sqlite3
from flask import Flask, render_template, request, redirect, url_for
app = Flask(__name__)
# --- Tạo database ---
def init_db():
conn = sqlite3.connect('students.db')
c = conn.cursor()
c.execute('''CREATE TABLE IF NOT EXISTS students (
id INTEGER PRIMARY KEY AUTOINCREMENT,
hoten TEXT,
lop TEXT,
diem REAL
)''')
conn.commit()
conn.close()
# --- Trang nhập học sinh ---
@app.route('/')
def index():
return render_template('index.html')
# --- Lưu học sinh mới ---
@app.route('/add', methods=['POST'])
def add():
hoten = request.form.get('hoten')
lop = request.form.get('lop')
diem = request.form.get('diem')
conn = sqlite3.connect('students.db')
c = conn.cursor()
c.execute("INSERT INTO students (hoten, lop, diem) VALUES (?, ?, ?)",
(hoten, lop, diem))
conn.commit()
conn.close()
return redirect('/list')
# --- Xem danh sách ---
@app.route('/list')
def list_students():
conn = sqlite3.connect('students.db')
c = conn.cursor()
c.execute("SELECT * FROM students")
data = c.fetchall()
conn.close()
return render_template('list.html', students=data)
# --- Chỉnh sửa ---
@app.route('/edit/', methods=['GET', 'POST'])
def edit(id):
conn = sqlite3.connect('students.db')
c = conn.cursor()
if request.method == 'POST':
hoten = request.form.get('hoten')
lop = request.form.get('lop')
diem = request.form.get('diem')
c.execute("UPDATE students SET hoten=?, lop=?, diem=? WHERE id=?",
(hoten, lop, diem, id))
conn.commit()
conn.close()
return redirect(url_for('list_students'))
else:
c.execute("SELECT * FROM students WHERE id=?", (id,))
data = c.fetchone()
conn.close()
return render_template('edit.html', hs=data)
# --- Xóa ---
@app.route('/delete/')
def delete(id):
conn = sqlite3.connect('students.db')
c = conn.cursor()
c.execute("DELETE FROM students WHERE id=?", (id,))
conn.commit()
conn.close()
return redirect('/list')
if __name__ == '__main__':
init_db()
app.run(debug=True)
-
/edit/<id> hiển thị form chỉnh sửa học sinh theo mã.-
/delete/<id> xóa học sinh được chọn.-
url_for() giúp Flask điều hướng linh hoạt.
📋 3. File templates/index.html – Form thêm học sinh
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<title>Thêm học sinh</title>
<style>
body { font-family: Arial; background: #e9f4ff; display: flex; justify-content: center; align-items: center; height: 100vh; }
.form-box { background: white; padding: 30px; border-radius: 8px; box-shadow: 0 0 10px rgba(0,0,0,0.2); width: 400px; }
input { width: 100%; padding: 8px; margin-top: 6px; border: 1px solid #ccc; border-radius: 5px; }
button { width: 100%; background: #2980b9; color: #fff; padding: 10px; border: none; border-radius: 5px; margin-top: 15px; }
a { display: block; text-align: center; margin-top: 10px; }
</style>
</head>
<body>
<form class="form-box" action="/add" method="POST">
<h2>➕ Thêm học sinh</h2>
<label>Họ và tên:</label>
<input type="text" name="hoten" required>
<label>Lớp:</label>
<input type="text" name="lop" required>
<label>Điểm trung bình:</label>
<input type="number" name="diem" min="0" max="10" step="0.1" required>
<button type="submit">Lưu học sinh</button>
<a href="/list">📋 Xem danh sách</a>
</form>
</body>
</html>
📄 4. File templates/list.html – Danh sách học sinh
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<title>Danh sách học sinh</title>
<style>
body { font-family: Arial; background: #f0f4f8; padding: 30px; }
table { width: 100%; border-collapse: collapse; margin-top: 15px; }
th, td { border: 1px solid #ccc; padding: 10px; text-align: center; }
th { background: #e9f2ff; }
a.button { background: #2980b9; color: white; padding: 6px 12px; border-radius: 5px; text-decoration: none; }
a.del { background: #e74c3c; }
</style>
</head>
<body>
<h2>📚 Danh sách học sinh</h2>
<table>
<tr>
<th>Mã</th><th>Họ tên</th><th>Lớp</th><th>Điểm TB</th><th>Hành động</th>
</tr>
{% for hs in students %}
<tr>
<td>{{ hs[0] }}</td><td>{{ hs[1] }}</td><td>{{ hs[2] }}</td><td>{{ hs[3] }}</td>
<td>
<a class="button" href="/edit/{{ hs[0] }}">✏️ Sửa</a>
<a class="button del" href="/delete/{{ hs[0] }}" onclick="return confirm('Bạn có chắc muốn xóa?')">🗑️ Xóa</a>
</td>
</tr>
{% endfor %}
</table>
<a href="/" class="button">➕ Thêm học sinh mới</a>
</body>
</html>
🧾 5. File templates/edit.html – Chỉnh sửa học sinh
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<title>Chỉnh sửa học sinh</title>
<style>
body { font-family: Arial; background: #f0f4f8; display: flex; justify-content: center; align-items: center; height: 100vh; }
.form-box { background: white; padding: 30px; border-radius: 8px; box-shadow: 0 0 10px rgba(0,0,0,0.2); width: 400px; }
input { width: 100%; padding: 8px; margin-top: 6px; border: 1px solid #ccc; border-radius: 5px; }
button { width: 100%; background: #2980b9; color: #fff; padding: 10px; border: none; border-radius: 5px; margin-top: 15px; }
</style>
</head>
<body>
<form class="form-box" method="POST">
<h2>✏️ Cập nhật học sinh</h2>
<label>Họ và tên:</label>
<input type="text" name="hoten" value="{{ hs[1] }}" required>
<label>Lớp:</label>
<input type="text" name="lop" value="{{ hs[2] }}" required>
<label>Điểm trung bình:</label>
<input type="number" name="diem" value="{{ hs[3] }}" min="0" max="10" step="0.1" required>
<button type="submit">Cập nhật</button>
<a href="/list">⬅️ Quay lại</a>
</form>
</body>
</html>
🏁 6. Kết quả khi chạy
Khi truy cập http://127.0.0.1:5000, bạn có thể:
- ➕ Thêm học sinh
- 📋 Xem danh sách
- ✏️ Sửa học sinh
- 🗑️ Xóa học sinh
🚀 7. Thử thách mở rộng cho học sinh
- Thêm ô tìm kiếm theo tên hoặc lớp.
- Thêm phân loại học lực (Giỏi – Khá – Trung bình).
- Làm trang thống kê tổng số học sinh và điểm TB cao nhất.
📚 Kết luận
- Bạn đã xây dựng được ứng dụng Flask hoàn chỉnh có cơ sở dữ liệu thực.
- Đây là mô hình chuẩn CRUD trong lập trình web.
- Có thể dùng kiến thức này để tạo ứng dụng quản lý học sinh, thư viện, hoặc câu lạc bộ trong trường.
© 2025 Trường THPT Phan Chu Trinh – Gia Lai | Bài giảng Flask – Phần 4: CRUD hoàn chỉnh
📌 Danh sách bình luận