2009-05-13 29 views
8

Trong Django, tôi có hai mô hình:Làm thế nào để làm tham gia truy vấn này trong Django

class Product(models.Model): 
    name = models.CharField(max_length = 50) 
    categories = models.ManyToManyField(Category) 

class ProductRank(models.Model): 
    product = models.ForeignKey(Product) 
    rank = models.IntegerField(default = 0) 

tôi đặt cấp bậc vào một bảng riêng biệt vì mỗi cái nhìn của một trang sẽ làm cho thứ hạng thay đổi và tôi đã rất lo lắng rằng tất cả các ghi này sẽ làm cho các truy vấn khác của tôi (chủ yếu là đọc) chậm lại.

tôi thu thập một danh sách các Products từ một truy vấn đơn giản:

cat = Category.objects.get(pk = 1) 
products = Product.objects.filter(categories = cat) 

bây giờ tôi muốn có được tất cả các cấp bậc cho các sản phẩm này. Tôi muốn làm tất cả trong một đi (sử dụng một tham gia SQL) và đã tự hỏi làm thế nào để thể hiện rằng bằng cách sử dụng cơ chế truy vấn của Django.

Cách thích hợp để thực hiện việc này ở Django là gì?

+0

Âm thanh như tối ưu hóa sớm. Bạn có bất kỳ bằng chứng profiler rằng "tất cả những viết này sẽ làm cho các truy vấn khác của tôi chậm lại"? Hoặc rằng hiệu ứng đó là tồi tệ hơn so với chậm xuống từ JOIN bổ sung khi bạn cần phải đọc thứ hạng? Viết nó một cách đơn giản đầu tiên và không tối ưu hóa cho đến khi bạn đã chứng minh rằng nó là cần thiết. –

Trả lời

12

này có thể được thực hiện trong Django, nhưng bạn sẽ cần phải tái cấu trúc mô hình của bạn hơi khác một chút:

class Product(models.Model): 
    name = models.CharField(max_length=50) 
    product_rank = models.OneToOneField('ProductRank') 

class ProductRank(models.Model): 
    rank = models.IntegerField(default=0) 

Bây giờ, khi lấy đối tượng Product, bạn có thể sau khi mối quan hệ một-một trong một truy vấn bằng cách sử dụng phương pháp select_related():

Product.objects.filter([...]).select_related() 

này sẽ tạo ra một truy vấn mà lấy về sản phẩm cấp bậc sử dụng một tham gia:

SELECT "example_product"."id", "example_product"."name", "example_product"."product_rank_id", "example_productrank"."id", "example_productrank"."rank" FROM "example_product" INNER JOIN "example_productrank" ON ("example_product"."product_rank_id" = "example_productrank"."id") 

Tôi phải di chuyển trường mối quan hệ giữa Sản phẩm và ProductRank sang mô hình Sản phẩm vì có vẻ như select_related() chỉ theo các khóa ngoại theo một hướng.

+0

Haha. Tôi chỉ đọc các tài liệu trên OneToOneField hôm nay và đã tự hỏi điều gì hữu ích cho nó! Cảm ơn về thông tin tuyệt vời. –

2

Thêm cuộc gọi vào phương thức select_related() của QuerySet, mặc dù tôi không tích cực lấy tham chiếu theo cả hai hướng, đó là câu trả lời có khả năng nhất.

4

tôi đã không kiểm tra nhưng:

products = Product.objects.filter(categories__pk=1).select_related() 

nên lấy mọi trường hợp.

Các vấn đề liên quan