Kỹ Thuật Tùy Chỉnh Manager Để Quản Lý Truy Vấn Trong Django

Trong Django ORM, Manager đóng vai trò là cổng giao tiếp chính để thực hiện các thao tác truy vấn dữ liệu ở cấp độ model. Mặc định, mỗi model đều có một manager tên là objects, tuy nhiên việc tạo ra các custom manager giúp đóng gói các logic truy vấn lặp lại, giúp code gọn gàng và dễ bảo trì hơn.

1. Khởi tạo Custom Manager

Để tạo một manager tùy chỉnh, bạn cần định nghĩa một class kế thừa từ models.Manager. Sau đó, gán instance của class này vào một attribute trong model.

class ProductManager(models.Manager):
    def get_stats(self):
        # Thực các xử lý logic phức tạp
        return self.all().count()

class Product(models.Model):
    title = models.CharField(max_length=200)
    items = ProductManager()

2. Đóng gói logic truy vấn

Giả sử bạn thường xuyên cần đếm số lượng sản phẩm đang hoạt động dựa trên một nhóm cụ thể. Thay vì viết lại query filter mỗi lần, hãy đưa nó vào manager.

Cách thông thường:

category = "electronics"
count = Product.objects.filter(category=category, status='active').count()

Sử dụng custom manager:

class ProductManager(models.Manager):
    def count_active_by_category(self, category):
        return self.filter(category=category, status='active').count()

class Product(models.Model):
    title = models.CharField(max_length=200)
    category = models.CharField(max_length=50)
    status = models.CharField(max_length=20)

    items = ProductManager()

Khi cần sử dụng:

total = Product.items.count_active_by_category("electronics")

Bạn có thể đặt tên attribute khác objects, miễn là đồng bộ khi gọi phương thức.

3. Tùy chỉnh QuerySet gốc

Phương thức get_queryset() quyết định tập hợp dữ liệu mặc định mà manager trả về. Các phương thức như all(), filter() đều dựa trên kết quả của hàm này.

Ví dụ, tạo một manager chỉ trả về các bản ghi đã được duyệt:

class ApprovedManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset().filter(is_approved=True)

class Article(models.Model):
    title = models.CharField(max_length=200)
    is_approved = models.BooleanField(default=False)

    objects = models.Manager()  # Manager mặc định
    approved = ApprovedManager() # Manager chỉ lấy bài duyệt

Lúc này:

Article.objects.all()  # Lấy tất cả bài viết
Article.approved.all()   # Chỉ lấy bài đã duyệt

Manager approved vẫn có thể chain thêm các điều kiện lọc khác mà vẫn giữ ràng buộc cơ bản là is_approved=True.

Article.approved.filter(title__icontains='django')

Thẻ: Django django-orm python custom-manager web-development

Đăng vào ngày 29 tháng 5 lúc 18:24