我已經看過幾個類似於這個問題的帖子,但沒有一個解決了我的問題。Django Rest Framework - 根據權限返回用戶或具有ModelViewSet的單個用戶列表
我正在使用Django Rest Framework的ModelViewSet。我有兩個視圖,一個詳細視圖和一個列表視圖。
我想要它,所以如果超級用戶訪問我的列表視圖,他會得到所有的用戶。如果普通用戶訪問列表視圖,他只能看到自己。
如果超級用戶訪問詳細視圖,他可以查看任何用戶。如果普通用戶訪問不是他的詳細視圖,他會得到一個認證錯誤。
我第一次嘗試使用權限,但意識到使用列表視圖的所有查詢集has_object_permission不運行,允許經過身份驗證的非超級用戶查看每個人。這是因爲對象權限只能用get命令運行。我試圖只覆蓋get_object,但get_object不被調用列表視圖,所以它沒有區別。所以我試圖覆蓋get_quertyset沒有get_objects,但這打破了我的細節視圖。
我的理解是,首先調用get_object作爲詳細視圖,然後調用get_queryset,如果我不覆蓋它們中的任何一個。但是,如果我重寫get_queryset,它會打破我的詳細信息視圖和get_object的正常功能(它不會基於主鍵進行篩選)。幕後必然會出現比我看到的更多的事情。必須有一種方法來編寫get_queryset來解決這個問題,即正常的Django版本,我不這樣做。
所以下面是我實現哪些工作,但我不明白爲什麼我必須重寫get_object。如果我只覆蓋get_queryset,那麼詳細信息視圖將被破壞,並以超級用戶身份登錄時返回所有用戶,而不是基於主鍵過濾的一個用戶。有沒有辦法來覆蓋get_queryset沒有get_object來解決這種行爲?
瀏覽:
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = (AllowPostAnyReadAuthenticatedUser,)
def get_queryset(self):
user = self.request.user
if user.is_superuser:
return User.objects.all()
return User.objects.filter(username=user.username)
def get_object(self):
obj = get_object_or_404(User.objects.filter(id=self.kwargs["pk"]))
self.check_object_permissions(self.request, obj)
return obj
權限:
class AllowPostAnyReadAuthenticatedUser(permissions.BasePermission):
def has_permission(self, request, view):
# Allow anyone to register
if request.method == "POST":
return True
# Must be authenticated to view
else:
return request.user and is_authenticated(request.user)
def has_object_permission(self, request, view, obj):
# Any view method requires you to be the user
return obj.id == request.user.id or request.user.is_superuser
串行:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('username', 'email', 'id', 'password')
read_only_fields = ('id',)
extra_kwargs = {
'password': {'write_only': True}
}
網址:
userList = views.UserViewSet.as_view({
'get': 'list',
'post': 'create'
})
userDetail = views.UserViewSet.as_view({
'get': 'retrieve',
'put': 'update',
'patch': 'partial_update',
'delete': 'destroy'
})
urlpatterns = [
url(r'^$', userList, name='users'),
url(r'^(?P<pk>\d+)$', userDetail, name='user'),
]
感謝您的迴應!如果我不覆蓋get_object,並且我是超級用戶,那麼由get_object調用的queryset將返回所有用戶,而不是與主鍵匹配的用戶(因爲覆蓋get_queryset將返回全部4個)。我不確定如何使get_queryset的行爲不同,如果它是一個詳細視圖與列表視圖(或者如果有一個pk列出vs不是)。所以detail_view會得到4個響應,這會導致錯誤。 – Diesel