2017-11-26 1 views
1

Django Rest Framework를 앱의 백엔드로 사용하고 있습니다.Django Rest Framework : 다른 모델을 기반으로 한 고급 쿼리 세트 필터링

User에는 Wallet이 있습니다. 그런 다음 나는 Item입니다. UserItem을 원할 경우 WalletWalletItem이라는 인스턴스를 만듭니다. 모든 것이 잘 작동합니다.

이제 User에 대한 항목 수를 limit_usage으로 제한하고 싶습니다.

우선, UserWallet에 항목 인스턴스의 수를 확인하는 새 인스턴스를 추가하는 방법을 추가하는 방법을 추가했습니다. 따라서 사용자는이 Item의 경우 limit_usage == 2 인 경우 세 번째를 추가 할 때 403을 얻습니다.

나는 익명의 사용자가 /items/를 호출하는 경우 응답 필터링되지 않은 항목이되도록 list()/ retrieve() 방법에 get_queryset() 방법 또는 queryset을 덮어 쓰려

. 그러나 사용자가 인증 된 경우 현재 사용자에 대해 limit_usage를 초과하지 않은 항목 만 지갑에 넣을 수있는 항목 만 필터링하고 싶습니다.

class Wallet(models.Model): 
    user = models.OneToOneField('auth.User', related_name='wallet') 

class Item(models.Model): 
    valid_from = models.DateTimeField() 
    valid_to = models.DateTimeField() 
    limit_usage = models.PositiveSmallIntegerField(default=0) 

class WalletItem(models.Model): 
    wallet = models.ForeignKey('Wallet', related_name='%(class)ss') 
    offer = models.ForeignKey('Item', related_name='offer') 

class ItemViewSet(viewsets.ReadOnlyModelViewSet): 
    queryset = Item.objects.all().order_by('-created_at') 
    serializer_class = ItemSerializer 

    def list(self, request, *args, **kwargs): 
     time_now = now() 
     self.queryset = self.queryset.filter(
      valid_from__lte=time_now, 
      valid_to__gte=time_now, 
     ) 
     serializer = self.get_serializer(self.queryset, many=True) 
     return Response(serializer.data) 

나는 나에게 도움이되어야 Item 클래스의 방법을 만들었지 만 나는이 검색어 세트에서 사용할 수 없습니다 실현 : 각 항목이 할 수 있는지 확인하기 위해

def is_visible_for_user(self, user=None): 
    if not self.limit_usage or not user: 
     return True 
    ct = WalletItem.objects.filter(item=self, wallet=user.wallet).count() 
    return self.limit_usage > ct 

그래서 나는의 검색어를 통해 반복 할 수 사용자가 볼 수 있지만 필터링 된 목록에서 쿼리 집합을 만들 수는 없습니다. 그래서 여기에 비슷한 것을 발견했습니다 : Django REST Framework : filtering with another table하지만 응답이 도움이되지 못했습니다.

답변

2

먼저 사용자가 인증되었는지 확인해야하며, 그렇지 않으면 Item을 모두 반환해야합니다. 해당 WalletItem 개체가 해당 제한을 초과하면 Item 개체를 걸러냅니다.

from django.db.models import Count, F, Sum 

... 

class ItemViewSet(viewsets.ReadOnlyModelViewSet): 
    def get_queryset(self): 
     queryset = super().get_queryset() 
     user = self.request.user 
     if user.is_anonymous: 
      return queryset 

     queryset = queryset.annotate(user_wallet_items=Sum(
      Case(
       When(walletitem__wallet_id=user.wallet_id, then=1), 
       default=0, output_field=IntegerField() 
      )) \ 
      .filter(user_wallet_items__lte=F('limit_usage')) 
     return queryset 

나는 거기 속해 이후이 같은 get_queryset() 방법에 현재 시간을 기준으로 여과를 이동하는 것이 좋습니다.

참고 :이 방법을 테스트하지 않았습니다.

+0

대단히 감사합니다. 매력처럼 작동합니다. 제한이없는 항목을 다루기 위해서'Q (limit_usage = 0)'만 추가했습니다. 귀하의 회신에 감사드립니다. 나는 완전히 새로운 [조건식] 세계를 발견했습니다. (https://docs.djangoproject.com/en/1.11/ref/models/conditional-expressions/) –

+0

@ JurajBezručka 당신은 환영합니다. 나는 대답하기 위해 준비하고 있었다. :) –

관련 문제