2017-10-01 11 views
0

두 모델이 있다고 가정 해 보겠습니다.Django Rest DRF : 역관계에 대한 개체 수 얻기

모델

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

class ItemRelation(models.Model): 
    item = models.ForeignKey(Item, related_name='relations_item') 
    user = models.ForeignKey(User, related_name='relations_user') 
    has_viewed = models.BooleanField(default=False) 
    has_loved = models.BooleanFields(default=False) 

지금, 내가 뭘 원하는 내가 장고 나머지 API를 사용하여 모든 항목에 대한 VIEW_COUNT 및 love_count을 얻고 싶은 것입니다.

views.py

class ItemView(ListAPIView): 
    queryset = Items.objects.all().prefetch_related(Prefetch('relations_item', 
      queryset=ItemRelation.objects.filter(Q(has_viewed=True) | Q(has_loved=True)) 
      ) 
    serializer_class = ItemSerializer 

음,이 계획했지만, 난 어떻게 목록-API-보기에서 각 항목에 대한 VIEW_COUNT 및 love_count을 얻는 전혀 생각이 없다. 필자는 시리얼 라이저에서 꽤 많은 것들을 시도했지만 작동하지 않을 것이라고 생각한다. 그러나 SerializerMethod()를 사용하여 작업을 수행 할 수 있지만 DB N + 1 횟수만큼 처리 할 수 ​​있습니다. prefetch_related에 대한 몇 가지 다른 블로그와 함께 문서를 읽었으며이 카운트 문제가 나타날 때까지 쉽게 작업을 수행 할 수있었습니다.

내 시리얼 라이저의 샘플.

class ItemSerializer(serializers.ModelSerializer): 

    class Meta: 
     model = Item 
     fields = ['name', 'relations_item'] 
+1

은'prefetch_related' 여기 적합한 도구 아니다; 당신은 실제 관련 객체를 신경 쓰지 않고 단지 카운트를 원합니다. [annotate] (https://docs.djangoproject.com/en/1.11/topics/db/aggregation/#generating-aggregates-for-each-item-in-a-queryset)이 필요합니다. –

+0

나는 적어도 db 히트로 그것을하고 싶다. count를 사용하면 API가 각 항목에 대해 db를 두 번 친다. 나는 여전히 주석을 올바르게 사용하는 방법을 찾지 못했고, 누군가가 보거나 사랑했는지 여부에 따라 참 또는 null 값을 얻습니다. 한 사람이 그것을 보거나 사랑한다면 사실이됩니다. 확실히 내가 뭔가 잘못하고있는 것을 확신합니다 ... – flaire

답변

1

난 당신이 관계의 수를 계산한다고 가정하는) has_viewed==True와 b) has_loved==True. annotate()Django Conditional Expressions으로 이용 가능해야한다

:

from django.db.models import Case, IntegerField, Sum, When 


class ItemView(ListAPIView): 
    queryset = Items.objects.annotate(
        view_count=Sum(
         When(relations_item__has_viewed=True, then=1), 
         output_field=IntegerField(), 
        ), 
        love_count=Sum(
         When(relations_item__has_loved=True, then=1), 
         output_field=IntegerField(), 
        ), 
       ) 
    # ... 
+1

아 ... 뷰에서 주석을 사용하도록되어 있었기 때문에 serializers 파일에서 동일한 작업을 수행하려고했습니다 : D Thanks – flaire