Django REST Framework个人数据的完整序列化

时间:2018-06-28 01:57:57

标签: django django-rest-framework

让经过身份验证的用户访问他们自己的私人信息,而其他用户只能访问公共信息的正确方法是什么?

我尝试创建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_serializerget_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)

2 个答案:

答案 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)