让经过身份验证的用户访问他们自己的私人信息,而其他用户只能访问公共信息的正确方法是什么?
我尝试创建2个序列化器:
from rest_framework import serializers
from app.models import User
class PublicUserSerializer(serializers.HyperlinkedModelSerializer):
image_url = serializers.ImageField(use_url=False)
class Meta:
model = User
fields = (
'pk',
'first_name',
'last_name',
'image_url',
)
lookup_field = 'pk'
extra_kwargs = {
'url': {'lookup_field': 'pk'}
}
class PrivateUserSerializer(PublicUserSerializer):
class Meta:
fields = (
'pk',
'first_name',
'last_name',
'image_url',
'details',
'email',
)
但是现在,我想知道如何更新视图集以选择适当的序列化器。
from rest_framework import viewsets
from app.authentication import FirebaseAuthentication
from app.models import User
from app.serializers import PublicUserSerializer, PrivateUserSerializer
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = PublicUserSerializer
lookup_field = 'pk'
authentication_classes = (FirebaseAuthentication,)
我可以覆盖get_serializer或get_serializer_class,但是如何使用此方法访问用户并检查权限?
解决方案:
序列化器:
from rest_framework import serializers
from app.models import User
class UserSerializer(serializers.HyperlinkedModelSerializer):
image_url = serializers.ImageField(use_url=False)
class Meta:
model = User
fields = [
'pk',
'first_name',
'last_name',
'image_url',
'details',
]
lookup_field = 'pk'
extra_kwargs = {
'url': {'lookup_field': 'pk'}
}
class PrivateUserSerializer(UserSerializer):
class Meta(UserSerializer.Meta):
fields = UserSerializer.Meta.fields + [
'email',
]
视图集:
from django.shortcuts import get_object_or_404
from rest_framework import viewsets
from rest_framework.response import Response
from app.authentication import FirebaseAuthentication
from app.models import User
from app.serializers import UserSerializer, PrivateUserSerializer
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
lookup_field = 'pk'
authentication_classes = (FirebaseAuthentication,)
def retrieve(self, request, pk=None):
queryset = User.objects.all()
user = get_object_or_404(queryset, pk=pk)
serializer = UserSerializer(user)
if self.request.user == user:
serializer = PrivateUserSerializer(user)
return Response(serializer.data)
答案 0 :(得分:1)
您将使用Django Rest Framework的权限
# Add this
from rest_framework.permissions import AllowAny
from rest_framework.permissions import IsAuthenticated
# Your other imports
from rest_framework import viewsets
from app.authentication import FirebaseAuthentication
from app.models import User
from app.serializers import PublicUserSerializer, PrivateUserSerializer
@permission_classes([AllowAny,])
class AllUsersViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = PublicUserSerializer
lookup_field = 'pk'
authentication_classes = (FirebaseAuthentication,)
# Apply whatever filters, permissions or logic specific for this level
@permission_classes([IsAuthenticated,])
class AuthenticatedUsersViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = PublicUserSerializer
lookup_field = 'pk'
authentication_classes = (FirebaseAuthentication,)
# Apply whatever filters, permissions or logic specific for this level
一旦视图集分离,就可以调整它们的逻辑。
答案 1 :(得分:1)
我认为,这将完成整个魔术工作:)
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = PublicUserSerializer
lookup_field = 'pk'
authentication_classes = (FirebaseAuthentication,)
def get_queryset(self):
if self.request.user: # If the user authenticated
return User.objects.filter(pk=self.request.user.id)
return User.objects.all() # user not authenticated
def get_serializer_class(self):
if self.request.user: # If the user authenticated
return PrivateUserSerializer
else: # user not authenticated
return PublicUserSerializer
def list(self, request, *args, **kwargs):
if self.request.user:
private_data = PrivateUserSerializer(User.objects.filter(pk=self.request.user.id),many=True).data
public_data = PublicUserSerializer(User.objects.exclude(pk=self.request.user.id),many=True).data
return Response(data=private_data+public_data)
return Response(data=PublicUserSerializer(User.objects.all(),many=True).data)
Fandekasp
的建议答案是
def retrieve(self, request, pk=None):
queryset = User.objects.all()
user = get_object_or_404(queryset, pk=pk)
if self.request.user == user:
serializer = PrivateUserSerializer(user)
else:
serializer = PublicUserSerializer(user)
return Response(serializer.data)