Django Rest Framework:基于另一个模型的高级查询集过滤

时间:2017-11-26 19:50:41

标签: python django rest django-rest-framework django-queryset

我使用Django Rest Framework作为应用程序的后端。

我的User有一个Wallet。然后我有Item。如果User想要Item,则会在他/她Wallet中创建一个名为WalletItem的实例。一切顺利。

现在,我想使用属性User限制limit_usage的项目数。

首先,我添加了一个检查以发布方法添加新实例,该实例检查User的{​​{1}}中的项目实例数。因此,当尝试为此Wallet WalletItem添加第三个limit_usage == 2时,用户会获得403。

我想在Item / get_queryset()方法中覆盖queryset方法或list(),这样,如果匿名用户调用retrieve(),则会有未过滤的项目响应。但是,如果用户通过身份验证,我只想过滤那些允许放入钱包的项目,即那些未超过当前用户的limit_usage的项目。

/items/

我创建了一个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

因此,我可以遍历查询集以查看每个项目是否对用户可见,但是我无法从此筛选列表中构造查询集。 我在SO上找到了类似的东西:Django REST Framework : filtering with another table但是回复对我没有帮助。

1 个答案:

答案 0 :(得分:3)

首先需要检查用户是否经过身份验证,不是,然后每{}返回} {}。然后,如果相应的Item对象超出其限制,则过滤掉Item个对象。

WalletItem

我建议您根据当前时间将过滤移至相同的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 方法,因为它属于那里。

注意:我没有测试过这种方法。