![](/img/trans.png)
[英]Django Rest Framework: Permissions based on Object Attributes/Ownership
[英]Django Rest Framework Permissions and Ownership
我有兩個簡單的模型
class User(AbstractUser):
pass
class Vacation(Model):
id = models.AutoField(primary_key=True)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
我不太確定對Django Rest Framework執行用戶權限的可伸縮方式是什么。 尤其是:
/vacation
端點上,用戶將看到一個過濾列表 /vacation/$id
端點上,如果不是所有者,則用戶將獲得403
以面向未來的方式實現此目標的最佳方法是什么。 說是否更深入:
謝謝!
從文檔:
REST框架中的權限始終定義為權限類列表。 在運行視圖主體之前,將檢查列表中的每個權限。 如果任何權限檢查失敗,則將引發exceptions.PermissionDenied或exceptions.NotAuthenticated異常,並且視圖主體將不運行。
REST框架權限還支持對象級權限。 對象級別權限用於確定是否應允許用戶對特定對象執行操作,該對象通常是模型實例。
根據您當前的需要,您可以定義自己的Permission類:
class IsVacationOwner(permissions.BasePermission):
# for view permission
def has_permission(self, request, view):
return request.user and request.user.is_authenticated
# for object level permissions
def has_object_permission(self, request, view, vacation_obj):
return vacation_obj.owner.id == request.user.id
並將此權限添加到您的視圖。 例如,在視圖集上:
class VacationViewSet(viewsets.ModelViewSet):
permission_classes = (IsVacationOwner,)
這里要注意一件事,因為您將使用'/vacations'
的過濾列表進行響應,因此請確保使用request.user
對其進行過濾。 因為對象級別權限將不適用於列表。
出於性能原因,返回對象列表時,通用視圖不會自動將對象級別權限應用於查詢集中的每個實例。
為了將來的需求,您始終可以在get_permissions
方法的幫助下get_permissions
設置權限。
class VacationViewSet(viewsets.ModelViewSet):
def get_permissions(self):
if self.action == 'list':
# vacations can be seen by anyone
# remember to remove the filter for list though
permission_classes = [IsAuthenticated]
# or maybe that special type of user you mentioned
# write a `IsSpecialUser` permission class first btw
permission_classes = [IsSpecialUser]
else:
permission_classes = [IsVacationOwner]
return [permission() for permission in permission_classes]
DRF具有出色的文檔 。 我希望這可以幫助您入門,並可以幫助您根據將來的需求使用不同的用例。
我建議您使用drf-viewsets
link 。 我們將使用vacation viewset
來完成這項工作。
from your_app.views import VacationViewSet
router.register('api/vacations/', VacationViewSet)
from rest_framework import serializers
from your_app.models import Vacation
class VacationSerializer(serializers.ModelSerializer):
class Meta:
model = Vacation
fields = ('id', 'owner',)
read_only_fields = ('id',)
在這里,我們將覆蓋viewset's
和list方法。 還有其他可能的方法,但是我最喜歡這種方法,因為我能夠看到代碼中正在發生的事情。 視圖集中繼承的Django模型鏈接的drf-mixins
retrive和列表的方法。
from rest_framework import viewsets, permissions, exceptions, status
from your_app.models import Vacation, User
from your_app.serializers import VacationSerializer
class VacationViewSet(viewsets.ModelViewSet):
queryset = Vacation.objects.all()
permission_classes = [IsAuthenticated]
serializer = VacationSerializer
# we are going to overwrite list and retrive
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
# now we are going to filter on user
queryset = queryset.filter(owner=self.request.user)
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
# not permitted check
if instance.owner is not self.request.user:
raise exceptions.PermissionDenied()
serializer = self.get_serializer(instance)
return Response(serializer.data)
Django rest框架為此提供了內置設置
只需導入所需的權限並將其添加到您的類變量permission_classes中
在my_name.api.views中
from rest_framework.permissions import ( AllowAny, IsAuthenticated, IsAdminUser, IsAuthenticatedOrReadOnly,)
class Vacation(ListAPIView):
serializer_class = VacationListSerializer
permission_classes = [IsAuthenticated]
您可以將多個權限類別添加為列表
此外,如果這樣做沒有幫助,您可以始終將模型對象過濾為
Mymodel.objects.filter(owner = self.request.user)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.