2009-12-05 2 views
15

này dường như không làm việc trong django 1.1 (Tôi tin rằng điều này sẽ đòi hỏi một subquery, do đó đến tiêu đề)Django chú thích truy vấn thiết lập với một số trên subquery

qs.annotate(interest_level= \ 
      Count(Q(tags__favoritedtag_set__user=request.user)) 
      ) 

Có mục trong bộ truy vấn của tôi được gắn thẻ và thẻ có thể được người dùng ưa thích, tôi muốn tính số lần người dùng đã yêu thích từng mục trong tập hợp thông qua thẻ.

có cách nào để tạo truy vấn như thế này mà không cần sử dụng thêm() không?

Cảm ơn.

+0

Bạn có nhận được thông báo lỗi không? Bạn có thể cung cấp các mô hình bạn đang làm việc không? – cethegeek

+0

lỗi là "ngoại lệ 'Q' đối tượng không có thuộc tính 'chia' ', geradeausanwalt là funcs tập hợp phải không có đối tượng Q làm đối số. Các mô hình trong câu trả lời của ông là tương tự như tôi. – Evgeny

Trả lời

10

Nhìn vào hàm add_aggregate trong phạm vi django/db/models/sql/query.py, đối tượng truy vấn sẽ không được chấp nhận làm giá trị đầu vào.

Thật không may, hiện tại không có cách nào trực tiếp trong Django để tổng hợp/chú thích về số tiền cho một queryset, đặc biệt không phải là một trong số đó được lọc thêm bằng cách nào đó.

Giả sử các mô hình sau:

class Item(models.Model): 
    name = models.CharField(max_length=32) 

class Tag(models.Model): 
    itemfk = models.ForeignKey(Item, related_name='tags') 
    name = models.CharField(max_length=32) 

class FavoritedTag(models.Model): 
    user = models.ForeignKey(User) 
    tag = models.ForeignKey(Tag) 

Ngoài ra, bạn không thể chú thích một queryset trên các lĩnh vực được xác định thông qua .extra().

Người ta có thể thả vào SQL trong views.py như vậy:

from testing.models import Item, Tag, FavoritedTag 
from django.shortcuts import render_to_response 
from django.contrib.auth.decorators import login_required 
from django.utils.datastructures import SortedDict 

@login_required 
def interest_level(request): 
    ruid = request.user.id 

    qs = Item.objects.extra(
     select = SortedDict([ 
      ('interest_level', 'SELECT COUNT(*) FROM testing_favoritedtag, testing_tag \ 
      WHERE testing_favoritedtag.user_id = %s \ 
      AND testing_favoritedtag.tag_id = testing_tag.id \ 
      AND testing_tag.itemfk_id = testing_item.id'), 
     ]), 
     select_params = (str(ruid),) 
    ) 

    return render_to_response('testing/interest_level.html', {'qs': qs}) 

mẫu:

{% for item in qs %} 
    name: {{ item.name }}, level: {{ item.interest_level }}<br> 
{% endfor %} 

Tôi thử nghiệm này sử dụng MySQL5. Vì tôi không có chuyên gia SQL mặc dù, tôi muốn được tò mò như thế nào để tối ưu hóa ở đây, hoặc nếu có một cách khác để "làm giảm" số lượng SQL. Có lẽ có một số cách thú vị để sử dụng các tính năng related_name ở đây trực tiếp trong SQL?

1

Nếu bạn muốn tránh rơi xuống SQL thô, một cách khác để làm cho con mèo này sử dụng phương pháp mô hình, sau đó sẽ cung cấp cho bạn thuộc tính mới trên mô hình để sử dụng trong các mẫu của bạn. Chưa được kiểm tra, nhưng một cái gì đó như thế này trên các Tags của bạn mô hình nên làm việc:

class Tag(models.Model): 
    itemfk = models.ForeignKey(Item, related_name='tags') 
    name = models.CharField(max_length=32) 

    def get_favetag_count(self): 
     """ 
     Calculate the number of times the current user has favorited a particular tag 
     """ 

     favetag_count = FavoritedTag.objects.filter(tag=self,user=request.user).count() 
     return favetag_count 

Sau đó, trong mẫu của bạn, bạn có thể sử dụng một cái gì đó như:

{{tag}} ({{tag.get_favetag_count}}) 

Nhược điểm của phương pháp này là nó có thể đạt cơ sở dữ liệu hơn nếu bạn đang ở trong một vòng lặp lớn hoặc một cái gì đó. Nhưng nói chung nó hoạt động tốt và được xung quanh không có khả năng chú thích để làm các truy vấn trên các mô hình liên quan. Và tránh phải sử dụng SQL thô.

+5

Không tương đương với chú thích ở tất cả, đó là vô cùng bất tiện. – hcalves