Cách sửa lỗi django.db.utils.OperationalError: (1146, "Table 'dbname.table_name' doesn't exist")

beginner🐍 Python2026-07-26| Django 2.2+, Python 3.x, MySQL, MariaDB, PostgreSQL, hoặc SQLite.

Error Message

django.db.utils.OperationalError: (1146, "Table 'dbname.table_name' doesn't exist")
#python#django#mysql#loi-database#migrations

Cách khắc phục trong 30 giây

Cơ sở dữ liệu của bạn về cơ bản đang báo rằng: "Tôi thấy yêu cầu của bạn, nhưng bảng đó không có trong hồ sơ của tôi." Thông thường, lý do đơn giản là bạn đã quên đẩy các thay đổi từ model vào schema thực tế của cơ sở dữ liệu. Hãy chạy hai lệnh sau để đồng bộ hóa chúng:

python manage.py makemigrations
python manage.py migrate

Nếu bạn đang làm việc trên một tính năng cụ thể, hãy nhắm trực tiếp vào ứng dụng đó để tránh các thông báo gây nhiễu:

python manage.py makemigrations your_app_name
python manage.py migrate your_app_name

Tại sao lỗi này xảy ra?

Lỗi 1146 là lỗi đặc thù của MySQL và MariaDB. Nó xảy ra khi Object-Relational Mapper (ORM) của Django cố gắng truy vấn một bảng không tồn tại trong cơ sở dữ liệu hiện tại của bạn. Đây không chỉ là vấn đề "thiếu bảng"; đó là sự mất đồng bộ giữa mã Python và schema SQL của bạn.

Các nguyên nhân phổ biến bao gồm:

  • Migration "ma": Bạn đã tạo một model Post mới với 10 trường, nhưng cơ sở dữ liệu vẫn chưa nhận được lệnh CREATE TABLE.
  • Lỗi đăng ký: Bạn quên thêm ứng dụng mới vào danh sách INSTALLED_APPS. Nếu Django không theo dõi ứng dụng đó, nó sẽ không tìm kiếm các file migration của ứng dụng đó.
  • Mã thực thi sớm (Eager Code): Bạn đã viết một truy vấn chạy ngay khi Python import một file (ví dụ: trong forms.py), trước khi cơ sở dữ liệu sẵn sàng.
  • Can thiệp thủ công: Ai đó (hoặc một script khác) đã xóa một bảng trực tiếp trong console MySQL, khiến bảng django_migrations của Django bị nhầm lẫn.

Các giải pháp từng bước

1. Kiểm tra đăng ký ứng dụng

Django sẽ bỏ qua các migration của bất kỳ ứng dụng nào không được đăng ký rõ ràng. Hãy mở file settings.py và xác nhận ứng dụng của bạn đã có mặt. Đây là một bước kiểm tra đơn giản nhưng có thể tiết kiệm hàng giờ debug.

# settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    # ...
    'blog_app',  # Đảm bảo tên ứng dụng của bạn chính xác tại đây
]

2. Giải quyết vấn đề truy vấn "Con gà và Quả trứng"

Một sai lầm thường gặp là thực hiện truy vấn cơ sở dữ liệu ở cấp cao nhất của một file. Ví dụ: nếu bạn định nghĩa các lựa chọn cho một menu thả xuống bằng cách lấy tất cả các category trực tiếp trong forms.py, Django sẽ cố gắng chạy lệnh SQL đó ngay khi bạn khởi động server.

# Đừng làm thế này! Nó sẽ chạy ngay khi import.
CATEGORIES = [(c.id, c.name) for c in Category.objects.all()]

class ProductForm(forms.Form):
    category = forms.ChoiceField(choices=CATEGORIES)

Nếu bảng category chưa tồn tại (chẳng hạn như trong lần migration đầu tiên), toàn bộ quá trình sẽ bị lỗi. Cách khắc phục: Sử dụng ModelChoiceField, nó hoạt động theo cơ chế "lazy" và chỉ truy vấn cơ sở dữ liệu khi form thực sự được sử dụng.

class ProductForm(forms.Form):
    # Cách này an toàn và gọn gàng hơn nhiều
    category = forms.ModelChoiceField(queryset=Category.objects.all())

3. Khôi phục từ các Migration mất đồng bộ

Đôi khi cơ sở dữ liệu của bạn nghĩ rằng một migration đã được áp dụng, nhưng bảng thực tế lại bị thiếu. Hoặc có thể bảng đã tồn tại, nhưng Django lại cố gắng tạo lại nó. Đây là lúc cờ --fake trở thành "cứu cánh" của bạn.

Nếu bảng đã tồn tại trong cơ sở dữ liệu nhưng Django vẫn tiếp tục cố gắng tạo nó, hãy yêu cầu Django ghi nhận migration đó là "đã xong" mà không cần chạy lệnh SQL:

python manage.py migrate your_app_name --fake

Nếu bạn cần bắt đầu lại từ đầu cho một ứng dụng cụ thể trong quá trình phát triển, bạn có thể xóa lịch sử migration của riêng ứng dụng đó:

  • Xóa lịch sử migration: python manage.py migrate --fake your_app_name zero
  • Xóa các file migration (ngoại trừ __init__.py) trong thư mục migrations/ của ứng dụng.
  • Tạo lại và áp dụng: python manage.py makemigrations sau đó là python manage.py migrate.

4. Xác minh trực tiếp trong cơ sở dữ liệu

Nếu bạn vẫn gặp lỗi, hãy kiểm tra kỹ hơn bên dưới hệ thống. Sử dụng Django shell để xem liệu ORM có thể kết nối với bảng hay không. Việc này chỉ mất năm giây và giúp loại trừ các vấn đề về cấu hình.

python manage.py shell

# Thử một truy vấn đếm đơn giản
from your_app_name.models import YourModel
print(YourModel.objects.count())

Nếu lệnh này trả về một con số (thậm chí là 0), bảng của bạn vẫn đang hoạt động tốt. Nếu nó tiếp tục báo lỗi 1146, hãy truy cập vào terminal SQL của bạn và chạy lệnh SHOW TABLES; để xem chính xác cơ sở dữ liệu đang chứa những gì.

Mẹo chuyên nghiệp: Môi trường đa cơ sở dữ liệu

Bạn đang làm việc với một cơ sở dữ liệu chính và một cơ sở dữ liệu phụ? Có thể Django đang tìm kiếm sai chỗ. Nếu bảng của bạn nằm trong một DB phụ, bạn phải chỉ định nó trong lệnh migration:

python manage.py migrate --database=external_db

Tài liệu tham khảo thêm

Related Error Notes