Trong quá trình làm việc với Django, việc kiểm tra sự tồn tại của một bản ghi trước khi thực hiện thao tác lưu trữ là yêu cầu rất phổ biến. Django cung cấp hai phương thức mạnh mẽ là get_or_create và update_or_create giúp tối ưu hóa luồng xử lý này, đảm bảo tính toàn vẹn của dữ liệu và giảm thiểu các đoạn mã kiểm tra điều kiện lặp lại.
Tìm hiểu về get_or_create
Phương thức get_or_create thực hiện truy vấn để tìm kiếm một bản ghi dựa trên các điều kiện lọc. Nếu bản ghi không tồn tại, nó sẽ khởi tạo và lưu bản ghi mới vào cơ sở dữ liệu. Kết quả trả về là một tuple chứa (object, created), trong đó created là giá trị boolean cho biết bản ghi đó mới được tạo hay đã có sẵn.
from myapp.models import Profile
# Điều kiện tìm kiếm và giá trị mặc định cho bản ghi mới
params = {'email': 'user@example.com'}
extras = {'username': 'new_user', 'is_active': True}
# Truy vấn hoặc tạo mới
profile, was_created = Profile.objects.get_or_create(**params, defaults=extras)
if was_created:
print("Đã tạo mới bản ghi người dùng.")
else:
print("Người dùng đã tồn tại.")
Tìm hiểu về update_or_create
Tương tự như get_or_create, nhưng update_or_create đi xa hơn một bước: nếu bản ghi đã tồn tại, nó sẽ thực hiện cập nhật các trường dữ liệu theo tham số truyền vào. Nếu chưa tồn tại, nó sẽ tạo mới hoàn toàn.
from myapp.models import Setting
# Tìm kiếm theo key, cập nhật value nếu tìm thấy
lookup_key = {'key': 'theme'}
new_data = {'value': 'dark_mode'}
obj, created = Setting.objects.update_or_create(defaults=new_data, **lookup_key)
if not created:
print("Đã cập nhật giá trị cho cài đặt hiện tại.")
Tình huống ứng dụng thực tế
Sự kết hợp giữa hai phương thức này đặc biệt hiệu quả khi xử lý dữ liệu từ các nguồn bên ngoài, như đồng bộ hóa bảng dữ liệu trung gian (staging table) vào các bảng chính có quan hệ khóa ngoại.
# Ví dụ xử lý đồng bộ dữ liệu vào bảng chính
raw_data_list = StagingTable.objects.all()
for entry in raw_data_list:
# Đảm bảo các đối tượng liên quan đã tồn tại trước khi tạo quan hệ
category, _ = Category.objects.get_or_create(slug=entry.cat_slug)
supplier, _ = Supplier.objects.get_or_create(code=entry.sup_code)
# Cập nhật hoặc tạo mới bản ghi sản phẩm với các khóa ngoại vừa lấy được
product, _ = Product.objects.update_or_create(
sku=entry.sku,
defaults={
'category': category,
'supplier': supplier,
'price': entry.price,
'stock': entry.stock,
'status': 'synced'
}
)
Cách tiếp cận này không chỉ giúp mã nguồn trở nên tinh gọn (clean code) mà còn hạn chế tối đa các lỗi vi phạm ràng buộc (constraint violation) khi chạy các tác vụ xử lý dữ liệu hàng loạt.