Python trong Phát triển Web: Django vs Flask

Khi bắt đầu hành trình phát triển web với Python, bạn sẽ gần như chắc chắn gặp hai cái tên: Django và Flask. Đây là hai framework phổ biến nhất trong hệ sinh thái Python backend, được sử dụng bởi hàng nghìn công ty từ startup đến tập đoàn lớn — Instagram, Pinterest, Spotify, Netflix, LinkedIn đều từng hoặc đang dùng một trong hai framework này.
Nhưng câu hỏi mà hầu hết developer mới đặt ra là: "Tôi nên học Django hay Flask?" Câu trả lời không đơn giản là framework nào "tốt hơn", mà là framework nào phù hợp hơn với mục tiêu, quy mô dự án, kinh nghiệm team và hướng phát triển sự nghiệp của bạn.
Bài viết này cung cấp cái nhìn toàn diện: so sánh chi tiết, ví dụ code thực tế, hướng dẫn quyết định, sai lầm thường gặp và tài nguyên học tập — giúp bạn chọn đúng công cụ và bắt đầu đúng hướng.
1. Giới thiệu: Bối cảnh phát triển web với Python
Python đã trở thành một trong những ngôn ngữ hàng đầu cho phát triển web backend nhờ cú pháp dễ đọc, hệ sinh thái thư viện phong phú và cộng đồng developer lớn. Theo các khảo sát Stack Overflow và GitHub, Python liên tục nằm trong top 3 ngôn ngữ được yêu thích và sử dụng nhiều nhất.
Trong thế giới Python web, có ba framework chính bạn cần biết:
| Framework | Triết lý | Ra đời | Đặc điểm nổi bật |
|---|---|---|---|
| Django | "Batteries included" | 2005 | Full-stack, ORM, admin, auth tích hợp |
| Flask | Microframework | 2010 | Tối giản, linh hoạt, dễ mở rộng |
| FastAPI | Modern API-first | 2018 | Async, type hints, auto OpenAPI docs |
Django và Flask đã tồn tại hơn một thập kỷ, có tài liệu phong phú, cộng đồng lớn và được kiểm chứng trong production. FastAPI là lựa chọn mới hơn, đang tăng trưởng nhanh — chúng ta sẽ đề cập ở phần riêng.
Lưu ý quan trọng: Không có framework nào "thay thế" framework kia. Nhiều developer senior thành thạo cả ba để linh hoạt chọn công cụ theo từng dự án.
2. Bảng so sánh tổng quan
Trước khi đi sâu vào từng framework, hãy nhìn bức tranh tổng thể:
| Tiêu chí | Django | Flask | FastAPI |
|---|---|---|---|
| Triết lý thiết kế | Monolithic, all-in-one | Microframework, plug-and-play | API-first, async-native |
| Kích thước core | Lớn (~2MB+) | Nhỏ gọn (~50 dòng core) | Trung bình |
| Độ khó học | Trung bình — nhiều concept | Dễ — bắt đầu trong 30 phút | Trung bình — cần hiểu type hints |
| ORM | Django ORM (tích hợp sẵn) | SQLAlchemy (cài thêm) | SQLAlchemy / Tortoise ORM |
| Admin panel | Có sẵn, rất mạnh | Không — Flask-Admin hoặc tự xây | Không — dùng third-party |
| Template engine | Django Template Language | Jinja2 | Không tích hợp (API thuần) |
| Authentication | Built-in, đầy đủ | Flask-Login, Flask-Security | OAuth2, JWT (cài thêm) |
| API / REST | Django REST Framework (DRF) | Flask-RESTful, tự viết | Native, rất mạnh |
| Async support | Django 4.1+ (đang phát triển) | Hạn chế (dùng Quart) | Native async/await |
| Performance | Tốt, có thể tối ưu | Nhẹ, nhanh cho API | Rất cao (Starlette/Uvicorn) |
| Phù hợp nhất | Website full-stack, CMS, e-commerce | API, microservice, prototype | API hiện đại, ML serving |
| Cộng đồng | Rất lớn, nhiều tài liệu VN | Lớn, nhiều tutorial | Đang tăng nhanh |
| Việc làm tại VN | Nhiều (outsourcing, startup) | Nhiều (API, fintech) | Đang tăng (startup tech) |
3. Django — Deep Dive
3.1. Triết lý "Batteries Included"
Django được xây dựng theo triết lý "batteries included" — mọi thứ bạn cần để xây dựng một website hoàn chỉnh đều có sẵn trong framework, không cần cài thêm hàng chục package riêng lẻ.
Các thành phần tích hợp sẵn:
- ORM: Truy vấn database bằng Python, migration tự động
- Admin panel: Giao diện quản trị dữ liệu ngay lập tức
- Authentication: User model, login, logout, permission, group
- Form handling: Validation, rendering, CSRF protection
- Template engine: Django Template Language (DTL)
- URL routing: Hệ thống URL declarative, rõ ràng
- Middleware: Xử lý request/response ở tầng trung gian
- Caching, sessions, messages: Tích hợp sẵn
3.2. Cấu trúc project Django
Một project Django điển hình có cấu trúc rõ ràng, giúp team làm việc thống nhất:
myproject/
├── manage.py
├── myproject/
│ ├── settings.py # Cấu hình toàn project
│ ├── urls.py # URL routing chính
│ └── wsgi.py # Entry point production
└── blog/ # App (module chức năng)
├── models.py # Định nghĩa database
├── views.py # Logic xử lý request
├── urls.py # URL của app
├── admin.py # Cấu hình admin panel
├── templates/ # HTML templates
└── migrations/ # Database migrations
3.3. Ví dụ: Tạo blog đơn giản với Django
Bước 1 — Khởi tạo project:
# Tạo virtual environment
python -m venv venv
source venv/bin/activate # macOS/Linux
# venv\Scripts\activate # Windows
# Cài Django và tạo project
pip install django
django-admin startproject myblog .
python manage.py startapp articles
Bước 2 — Định nghĩa model:
# articles/models.py
from django.db import models
from django.contrib.auth.models import User
class Article(models.Model):
STATUS_CHOICES = [
('draft', 'Bản nháp'),
('published', 'Đã xuất bản'),
]
title = models.CharField(max_length=200, verbose_name="Tiêu đề")
slug = models.SlugField(unique=True)
content = models.TextField(verbose_name="Nội dung")
author = models.ForeignKey(User, on_delete=models.CASCADE)
status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='draft')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['-created_at']
verbose_name = "Bài viết"
def __str__(self):
return self.title
Bước 3 — Đăng ký admin panel (chỉ vài dòng):
# articles/admin.py
from django.contrib import admin
from .models import Article
@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
list_display = ['title', 'author', 'status', 'created_at']
list_filter = ['status', 'created_at']
search_fields = ['title', 'content']
prepopulated_fields = {'slug': ('title',)}
Bước 4 — View và URL:
# articles/views.py
from django.shortcuts import render, get_object_or_404
from .models import Article
def article_list(request):
articles = Article.objects.filter(status='published')
return render(request, 'articles/list.html', {'articles': articles})
def article_detail(request, slug):
article = get_object_or_404(Article, slug=slug, status='published')
return render(request, 'articles/detail.html', {'article': article})
# articles/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.article_list, name='article_list'),
path('<slug:slug>/', views.article_detail, name='article_detail'),
]
Bước 5 — Chạy migration và server:
python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser
python manage.py runserver
Truy cập http://127.0.0.1:8000/admin/ — bạn đã có admin panel hoàn chỉnh để quản lý bài viết mà không cần viết thêm một dòng HTML nào.
3.4. Django REST Framework (DRF)
Khi cần xây API, Django không bắt bạn chuyển sang framework khác. Django REST Framework là extension phổ biến nhất:
# articles/serializers.py
from rest_framework import serializers
from .models import Article
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = ['id', 'title', 'slug', 'content', 'author', 'created_at']
read_only_fields = ['author', 'created_at']
# articles/views.py (API)
from rest_framework import viewsets, permissions
from .models import Article
from .serializers import ArticleSerializer
class ArticleViewSet(viewsets.ModelViewSet):
queryset = Article.objects.filter(status='published')
serializer_class = ArticleSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
def perform_create(self, serializer):
serializer.save(author=self.request.user)
3.5. Điểm mạnh và hạn chế của Django
Điểm mạnh:
- Ship nhanh: admin, auth, ORM sẵn sàng ngay từ ngày đầu
- Bảo mật tốt: CSRF, XSS, SQL injection được xử lý mặc định
- Convention rõ ràng: team mới onboard nhanh
- Ecosystem lớn: django-allauth, django-celery-beat, django-storages...
- Phù hợp dự án lớn, dài hạn
Hạn chế:
- "Nặng" cho dự án nhỏ — nhiều boilerplate không cần thiết
- Linh hoạt kém hơn Flask — phải theo convention của Django
- Async vẫn đang phát triển — chưa mature như FastAPI
- Learning curve cao hơn — nhiều concept (middleware, signals, apps...)
3.6. Dự án thực tế dùng Django
| Dự án / Công ty | Mô tả | Tại sao chọn Django |
|---|---|---|
| Mạng xã hội chia sẻ ảnh | ORM mạnh, scale tốt, team lớn | |
| Nền tảng bookmark hình ảnh | Admin, CMS, xử lý content | |
| Mozilla Add-ons | Cửa hàng extension trình duyệt | Bảo mật, user management |
| Disqus | Hệ thống comment | Xử lý traffic lớn, auth |
| Bitbucket (trước đây) | Git hosting | Full-stack, permission system |
4. Flask — Deep Dive
4.1. Triết lý Microframework
Flask được tạo ra bởi Armin Ronacher với triết lý ngược lại Django: chỉ cung cấp tối thiểu, phần còn lại do developer tự quyết định.
Core của Flask chỉ gồm:
- Routing (ánh xạ URL → function)
- Request/response handling
- Jinja2 template engine
- Session management cơ bản
Mọi thứ khác — database, authentication, form validation, caching — bạn tự chọn và tích hợp.
4.2. Cấu trúc project Flask
Flask không ép cấu trúc cố định. Dự án nhỏ có thể chỉ một file app.py. Dự án lớn thường dùng Application Factory pattern:
myapi/
├── app/
│ ├── __init__.py # Application factory
│ ├── models.py # SQLAlchemy models
│ ├── routes/
│ │ ├── auth.py
│ │ └── products.py
│ ├── services/ # Business logic
│ └── templates/
├── config.py
├── requirements.txt
└── run.py
4.3. Ví dụ: RESTful API với Flask
Bước 1 — Cài đặt:
python -m venv venv
source venv/bin/activate
pip install flask flask-sqlalchemy flask-migrate flask-jwt-extended
Bước 2 — Application factory:
# app/__init__.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
db = SQLAlchemy()
migrate = Migrate()
def create_app(config_name='development'):
app = Flask(__name__)
app.config.from_object(f'config.{config_name.capitalize()}Config')
db.init_app(app)
migrate.init_app(app, db)
from app.routes import products, auth
app.register_blueprint(products.bp)
app.register_blueprint(auth.bp)
return app
Bước 3 — Model với SQLAlchemy:
# app/models.py
from app import db
from datetime import datetime
class Product(db.Model):
__tablename__ = 'products'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)
price = db.Column(db.Numeric(12, 2), nullable=False)
stock = db.Column(db.Integer, default=0)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
def to_dict(self):
return {
'id': self.id,
'name': self.name,
'price': float(self.price),
'stock': self.stock,
}
Bước 4 — API routes:
# app/routes/products.py
from flask import Blueprint, request, jsonify
from app import db
from app.models import Product
bp = Blueprint('products', __name__, url_prefix='/api/products')
@bp.route('/', methods=['GET'])
def list_products():
products = Product.query.all()
return jsonify([p.to_dict() for p in products])
@bp.route('/', methods=['POST'])
def create_product():
data = request.get_json()
product = Product(
name=data['name'],
price=data['price'],
stock=data.get('stock', 0)
)
db.session.add(product)
db.session.commit()
return jsonify(product.to_dict()), 201
@bp.route('/<int:product_id>', methods=['GET'])
def get_product(product_id):
product = Product.query.get_or_404(product_id)
return jsonify(product.to_dict())
Bước 5 — Chạy ứng dụng:
export FLASK_APP=run.py
flask db init
flask db migrate -m "Initial migration"
flask db upgrade
flask run
4.4. Flask Blueprints — Tổ chức code quy mô lớn
Khi project phình to, Blueprints giúp chia nhỏ ứng dụng thành các module độc lập:
# app/routes/auth.py
from flask import Blueprint, request, jsonify
from flask_jwt_extended import create_access_token
bp = Blueprint('auth', __name__, url_prefix='/api/auth')
@bp.route('/login', methods=['POST'])
def login():
data = request.get_json()
# Xác thực user...
access_token = create_access_token(identity=data['username'])
return jsonify(access_token=access_token)
4.5. Điểm mạnh và hạn chế của Flask
Điểm mạnh:
- Bắt đầu cực nhanh — 5 dòng code là có web server
- Kiểm soát hoàn toàn kiến trúc
- Nhẹ, footprint nhỏ — lý tưởng cho microservice
- Ecosystem mở — tích hợp tự do SQLAlchemy, Celery, Redis
- Dễ học — concept ít, tài liệu rõ ràng
Hạn chế:
- Phải tự quyết định mọi thứ — dễ "analysis paralysis"
- Không có admin panel sẵn
- Không có convention cố định — team lớn cần tự đặt quy tắc
- Async hạn chế — cần Quart nếu muốn async native
4.6. Dự án thực tế dùng Flask
| Dự án / Công ty | Mô tả | Tại sao chọn Flask |
|---|---|---|
| Netflix | Một số internal tools | Microservice, API nhẹ |
| Internal APIs | Linh hoạt, tích hợp hệ thống có sẵn | |
| Reddit (trước đây) | Nền tảng forum | Prototype nhanh, scale dần |
| Lyft | Một số backend services | Microservice architecture |
| Zalando | E-commerce APIs | API-first, team tự chọn stack |

5. FastAPI — Lựa chọn thứ ba đáng cân nhắc
Ngoài Django và Flask, FastAPI đang trở thành lựa chọn phổ biến thứ ba — đặc biệt cho API backend hiện đại.
5.1. Tại sao FastAPI xuất hiện?
FastAPI ra đời năm 2018, giải quyết các hạn chế của Flask và Django trong bối cảnh:
- Frontend tách biệt (React, Vue, mobile app) cần API thuần
- Yêu cầu hiệu suất cao với async I/O
- Type hints trở thành chuẩn trong Python 3.6+
- Cần tài liệu API tự động (OpenAPI/Swagger)
5.2. Ví dụ FastAPI
# main.py
from fastapi import FastAPI, HTTPException, Depends
from pydantic import BaseModel
from typing import List
app = FastAPI(title="Product API", version="1.0")
class ProductCreate(BaseModel):
name: str
price: float
stock: int = 0
class ProductResponse(BaseModel):
id: int
name: str
price: float
stock: int
class Config:
from_attributes = True
# Database giả lập
products_db: List[dict] = []
counter = 0
@app.get("/api/products", response_model=List[ProductResponse])
async def list_products():
return products_db
@app.post("/api/products", response_model=ProductResponse, status_code=201)
async def create_product(product: ProductCreate):
global counter
counter += 1
new_product = {"id": counter, **product.model_dump()}
products_db.append(new_product)
return new_product
@app.get("/api/products/{product_id}", response_model=ProductResponse)
async def get_product(product_id: int):
for p in products_db:
if p["id"] == product_id:
return p
raise HTTPException(status_code=404, detail="Product not found")
pip install fastapi uvicorn
uvicorn main:app --reload
# Truy cập http://127.0.0.1:8000/docs — Swagger UI tự động!
5.3. Khi nào chọn FastAPI thay vì Flask/Django?
| Tình huống | FastAPI | Flask | Django |
|---|---|---|---|
| API backend cho SPA/mobile | ✅ Tốt nhất | ✅ Được | ⚠️ DRF, nặng hơn |
| ML model serving | ✅ Rất phù hợp | ⚠️ Được | ❌ Quá nặng |
| Website full-stack với admin | ❌ Không phù hợp | ⚠️ Tự xây nhiều | ✅ Tốt nhất |
| Microservice async | ✅ Native async | ❌ Hạn chế | ⚠️ Đang phát triển |
| Team mới học backend | ⚠️ Cần hiểu type hints | ✅ Dễ nhất | ⚠️ Nhiều concept |
| Auto API documentation | ✅ Swagger/ReDoc sẵn | ❌ Tự viết | ⚠️ DRF có, cần cấu hình |
6. So sánh chi tiết theo từng khía cạnh
6.1. Database và ORM
Django ORM:
# Truy vấn phức tạp với Django ORM
from django.db.models import Count, Avg
stats = Article.objects.filter(status='published') \
.values('author__username') \
.annotate(
total_articles=Count('id'),
avg_title_length=Avg('title__length')
)
SQLAlchemy (Flask/FastAPI):
from sqlalchemy import func
stats = db.session.query(
User.username,
func.count(Article.id).label('total'),
func.avg(func.length(Article.title)).label('avg_length')
).join(Article).filter(Article.status == 'published') \
.group_by(User.username).all()
| Khía cạnh | Django ORM | SQLAlchemy |
|---|---|---|
| Migration | makemigrations + migrate tự động | Flask-Migrate / Alembic |
| Raw SQL | Model.objects.raw() | db.session.execute() |
| Relationship | ForeignKey, ManyToMany tích hợp | relationship(), backref |
| Learning curve | Trung bình | Trung bình-cao |
| Linh hoạt | Theo convention Django | Rất linh hoạt |
6.2. Authentication và Authorization
Django — Built-in:
from django.contrib.auth.decorators import login_required, permission_required
@login_required
@permission_required('articles.change_article', raise_exception=True)
def edit_article(request, pk):
# Chỉ user đã login và có quyền mới truy cập được
...
Flask — Flask-Login + JWT:
from flask_jwt_extended import jwt_required, get_jwt_identity
@app.route('/api/profile')
@jwt_required()
def profile():
current_user = get_jwt_identity()
return jsonify(user=current_user)
6.3. Testing
Django Test Client:
from django.test import TestCase, Client
class ArticleTestCase(TestCase):
def setUp(self):
self.client = Client()
self.user = User.objects.create_user('testuser', password='test123')
def test_article_list(self):
response = self.client.get('/articles/')
self.assertEqual(response.status_code, 200)
Flask + pytest:
import pytest
@pytest.fixture
def client():
app = create_app('testing')
with app.test_client() as client:
yield client
def test_list_products(client):
response = client.get('/api/products/')
assert response.status_code == 200
assert isinstance(response.json, list)
6.4. Triển khai Production
Cả ba framework đều triển khai production tương tự:
# Django
pip install gunicorn
gunicorn myproject.wsgi:application --bind 0.0.0.0:8000 --workers 4
# Flask
gunicorn "app:create_app()" --bind 0.0.0.0:5000 --workers 4
# FastAPI
pip install uvicorn gunicorn
gunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000
Kết hợp với Nginx làm reverse proxy và Docker để containerize là setup phổ biến nhất.
7. Use cases — Khi nào dùng framework nào?
7.1. Chọn Django khi...
- Xây website hoàn chỉnh: blog, CMS, portal nội bộ, e-commerce
- Cần admin panel ngay từ đầu để quản lý dữ liệu
- Team lớn, cần convention thống nhất và onboarding nhanh
- Dự án có user management phức tạp: role, permission, group
- Deadline gấp — cần ship nhanh với tính năng tích hợp sẵn
- Làm việc với agency/outsourcing tại Việt Nam (nhiều job Django)
7.2. Chọn Flask khi...
- Xây RESTful API đơn giản, không cần admin
- Prototype/MVP cần hoàn thành trong vài ngày
- Microservice trong kiến trúc phân tán
- Cần kiểm soát hoàn toàn kiến trúc và dependencies
- Tích hợp với hệ thống có sẵn (legacy system, frontend riêng)
- Team nhỏ (1-3 người), dự án ngắn hạn
7.3. Chọn FastAPI khi...
- Xây API backend hiện đại cho SPA (React, Vue) hoặc mobile
- Cần hiệu suất cao với async I/O (WebSocket, streaming)
- ML model serving — deploy model Python thành API
- Muốn tài liệu API tự động (Swagger UI)
- Team đã quen type hints và Pydantic validation
- Startup tech cần iterate nhanh với API contract rõ ràng
8. Bảng hướng dẫn quyết định
| Bạn cần... | Framework đề xuất | Lý do |
|---|---|---|
| Website hoàn chỉnh với admin | Django | Admin panel, auth, ORM sẵn sàng |
| RESTful API đơn giản | Flask hoặc FastAPI | Nhẹ, nhanh, linh hoạt |
| E-commerce, CMS | Django | django-oscar, wagtail, mezzanine |
| Microservice | Flask hoặc FastAPI | Footprint nhỏ, deploy độc lập |
| ML model API | FastAPI | Async, Pydantic, dễ tích hợp ML libs |
| Học web dev từ đầu | Django | Học được nhiều concept nhất |
| Kiểm soát hoàn toàn kiến trúc | Flask | Không bị ép convention |
| API với auto documentation | FastAPI | Swagger/ReDoc tự động |
| Dự án outsourcing VN | Django | Nhiều job, tài liệu VN phong phú |
| Hackathon / MVP 48h | Flask | Bắt đầu nhanh nhất |
| Real-time (WebSocket) | FastAPI | Native WebSocket support |
| Multi-tenant SaaS | Django | django-tenants, auth mạnh |
9. Ví dụ dự án thực tế theo framework
9.1. Dự án Django: Hệ thống quản lý khóa học online
Yêu cầu: Website đăng ký khóa học, quản lý học viên, giảng viên, thanh toán, admin panel.
Tại sao Django:
- Admin panel quản lý khóa học, học viên ngay lập tức
- User model mở rộng cho giảng viên/học viên
- Django ORM xử lý relationship phức tạp (khóa học → bài học → bài tập)
- django-allauth cho đăng nhập Google/Facebook
- DRF cho mobile app API
Stack điển hình:
Django + PostgreSQL + Redis + Celery + DRF + django-allauth
9.2. Dự án Flask: API thanh toán nội bộ
Yêu cầu: Microservice xử lý giao dịch, tích hợp với 3 service khác qua message queue.
Tại sao Flask:
- Service nhỏ, chỉ cần API — không cần admin hay template
- Tích hợp linh hoạt với RabbitMQ, Redis
- Deploy độc lập, scale horizontal
- Team 2 người, cần kiểm soát hoàn toàn
Stack điển hình:
Flask + SQLAlchemy + PostgreSQL + Celery + RabbitMQ + JWT
9.3. Dự án FastAPI: ML Recommendation API
Yêu cầu: API gợi ý sản phẩm real-time, tích hợp model scikit-learn, frontend React.
Tại sao FastAPI:
- Async xử lý nhiều request đồng thời
- Pydantic validate input/output rõ ràng
- Swagger docs cho team frontend tự test API
- Dễ load model ML vào memory khi startup
Stack điển hình:
FastAPI + SQLAlchemy + PostgreSQL + Redis + scikit-learn + Uvicorn
10. Sai lầm thường gặp
10.1. Sai lầm khi dùng Django
1. Không tách logic ra khỏi views (Fat Views)
# ❌ Sai — logic business nằm trong view
def create_order(request):
# 50 dòng code xử lý đơn hàng, tính giá, gửi email...
pass
# ✅ Đúng — tách ra service layer
def create_order(request):
order = OrderService.create_from_cart(request.user, request.POST)
return redirect('order_detail', pk=order.pk)
2. Bỏ qua select_related / prefetch_related — gây N+1 query
# ❌ Sai — mỗi article gọi thêm 1 query lấy author
articles = Article.objects.all()
for a in articles:
print(a.author.username) # N+1 queries!
# ✅ Đúng
articles = Article.objects.select_related('author').all()
3. Hardcode SECRET_KEY và DEBUG=True trong production
# ❌ Nguy hiểm
SECRET_KEY = 'my-secret-key-123'
DEBUG = True
# ✅ Dùng biến môi trường
import os
SECRET_KEY = os.environ['DJANGO_SECRET_KEY']
DEBUG = os.environ.get('DEBUG', 'False') == 'True'
10.2. Sai lầm khi dùng Flask
1. Để tất cả code trong một file app.py
Khi project > 200 dòng, hãy chuyển sang Application Factory + Blueprints ngay.
2. Không dùng migration cho database
# ❌ Tạo bảng thủ công hoặc db.create_all() trong production
# ✅ Luôn dùng Flask-Migrate
flask db migrate -m "Add products table"
flask db upgrade
3. Quên bật CSRF protection cho form
# ✅ Dùng Flask-WTF
from flask_wtf.csrf import CSRFProtect
csrf = CSRFProtect(app)
10.3. Sai lầm chung
| Sai lầm | Hậu quả | Cách tránh |
|---|---|---|
| Chọn framework theo trend, không theo dự án | Over-engineering hoặc thiếu tính năng | Phân tích yêu cầu trước khi chọn |
| Không dùng virtual environment | Conflict dependencies | Luôn python -m venv venv |
Deploy development server (runserver/flask run) | Không an toàn, không scale | Dùng Gunicorn/Uvicorn + Nginx |
| Không viết test | Bug production, refactor sợ | Viết test cho logic quan trọng |
| Học framework mà bỏ qua Python cơ bản | Hiểu nông, debug khó | Nắm vững OOP, decorator, context manager |
11. Tài nguyên học tập
11.1. Django
| Tài nguyên | Loại | Mô tả |
|---|---|---|
| Django Docs chính thức | Tài liệu | Đầy đủ, cập nhật, có tiếng Anh |
| Django for Beginners | Sách | William S. Vincent — rất phù hợp người mới |
| Django Girls Tutorial | Tutorial | Miễn phí, thực hành từng bước |
| Mozilla Django Tutorial | Tutorial | MDN — chất lượng cao |
| Django REST Framework Docs | Tài liệu | Bắt buộc nếu làm API với Django |
11.2. Flask
| Tài nguyên | Loại | Mô tả |
|---|---|---|
| Flask Docs chính thức | Tài liệu | Ngắn gọn, dễ hiểu |
| Flask Mega-Tutorial | Tutorial | Miguel Grinberg — kinh điển |
| Flask Web Development | Sách | Cùng tác giả Mega-Tutorial |
| Real Python Flask Tutorials | Tutorial | Nhiều chủ đề thực tế |
11.3. FastAPI
| Tài nguyên | Loại | Mô tả |
|---|---|---|
| FastAPI Tutorial | Tài liệu | Tài liệu chính thức, rất tốt |
| FastAPI Best Practices | GitHub | Patterns cho dự án lớn |
| Full Stack FastAPI Template | Template | Project mẫu production-ready |
11.4. Lộ trình học đề xuất
Tuần 1-2: Python cơ bản + OOP + virtual environment
Tuần 3-4: Chọn 1 framework → làm project CRUD đầu tiên
Tuần 5-6: Authentication + database migration + testing
Tuần 7-8: Deploy lên server (Heroku/Railway/DigitalOcean)
Tuần 9+: Học framework thứ 2 + so sánh thực tế
12. FAQ — Câu hỏi thường gặp
Câu 1: Tôi mới học Python, nên bắt đầu với Django hay Flask?
Flask nếu bạn muốn thấy kết quả nhanh và hiểu từng thành phần một cách rõ ràng. Django nếu bạn muốn học web development một cách có hệ thống và sẵn sàng đầu tư thời gian học nhiều concept hơn. Cả hai đều phù hợp cho người mới — quan trọng là bắt đầu và làm project thực tế, đừng mắc kẹt ở việc chọn framework quá lâu.
Câu 2: Django có chậm hơn Flask không?
Trong hầu hết trường hợp thực tế, sự khác biệt hiệu suất không đáng kể so với bottleneck thực sự (database query, network I/O). Django có thể chậm hơn nếu bạn viết N+1 queries hoặc không cache — nhưng đó là vấn đề của developer, không phải framework. Cả hai đều xử lý hàng nghìn request/giây khi được cấu hình đúng với Gunicorn + Nginx.
Câu 3: Có nên học cả Django lẫn Flask không?
Có, và nên thêm FastAPI nữa. Mỗi framework dạy bạn cách tiếp cận khác nhau. Trong sự nghiệp thực tế, bạn sẽ gặp cả ba. Học Django giúp bạn hiểu convention và cấu trúc project lớn. Học Flask giúp bạn hiểu kiến trúc từ đầu. Học FastAPI giúp bạn nắm bắt xu hướng API hiện đại.
Câu 4: FastAPI có thay thế Flask và Django không?
Không hoàn toàn. FastAPI xuất sắc cho API backend nhưng không phù hợp khi bạn cần website full-stack với admin panel, template rendering phức tạp, hoặc hệ thống user management đầy đủ. Django vẫn vững cho dự án lớn. Flask vẫn lý tưởng cho microservice nhẹ. FastAPI bổ sung cho khoảng trống mà hai framework kia chưa lấp đầy tốt.
Câu 5: Framework nào có nhiều việc làm nhất tại Việt Nam?
Hiện tại Django vẫn chiếm ưu thế trong các công ty outsourcing và agency tại Việt Nam, đặc biệt các dự án web app, CMS, e-commerce. Flask phổ biến trong fintech và startup cần API. FastAPI đang tăng nhanh ở các startup tech và công ty AI/ML. Tuy nhiên, nhu cầu nhân sự Python backend nói chung đang tăng — biết cả ba sẽ giúp bạn linh hoạt hơn trên thị trường.
13. Kết luận
Django, Flask và FastAPI đều là những framework xuất sắc — không có "người thắng" tuyệt đối, chỉ có lựa chọn phù hợp với từng bối cảnh:
- Django — lựa chọn mạnh mẽ khi bạn cần xây website hoàn chỉnh, admin panel, user management và muốn ship nhanh với convention rõ ràng.
- Flask — lựa chọn linh hoạt khi bạn cần API nhẹ, microservice, prototype hoặc muốn kiểm soát hoàn toàn kiến trúc.
- FastAPI — lựa chọn hiện đại khi bạn tập trung vào API backend, cần async, type safety và tài liệu API tự động.
Lời khuyên cuối: Đừng mất quá 1 tuần để chọn framework. Hãy chọn một, làm xong một project CRUD hoàn chỉnh (có auth, database, deploy), rồi quay lại đánh giá. Kinh nghiệm thực tế luôn quý hơn mọi bảng so sánh lý thuyết.
Dù bạn chọn framework nào, nền tảng Python vững chắc — OOP, xử lý exception, làm việc với database, viết test — mới là thứ quyết định bạn trở thành backend developer giỏi hay không. Framework chỉ là công cụ; kỹ năng tư duy và giải quyết vấn đề mới là tài sản lâu dài.
Bắt đầu hôm nay. Ship project đầu tiên trong tuần này.