has_object_permission is called only by get_object(), not on list endpoints.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | # ====================================================================== # Q: Write a custom permission: a user sees only the orders of their own # company, and only a manager can cancel. # # has_object_permission is called only by get_object(), not on list endpoints. # That is why filtering in get_queryset() is mandatory. # ====================================================================== class IsCompanyManager(BasePermission): def has_permission(self, request, view): return request.user.is_authenticated def has_object_permission(self, request, view, obj): if obj.customer.company_id != request.user.company_id: return False if view.action == 'cancel': return request.user.role == 'manager' return True class OrderViewSet(viewsets.ReadOnlyModelViewSet): permission_classes = [IsCompanyManager] serializer_class = OrderSerializer def get_queryset(self): # the first and most important filter return (Order.objects.filter(customer__company_id=self.request.user.company_id) .select_related('customer').prefetch_related('items__product')) @action(detail=True, methods=['post']) def cancel(self, request, pk=None): order = self.get_object() # calls has_object_permission services.cancel_order(order, by=request.user) return Response(status=status.HTTP_204_NO_CONTENT) |