Django REST Framework полная сериализация для персональных данных - PullRequest
0 голосов
/ 28 июня 2018

Как правильно разрешить аутентифицированным пользователям получать доступ к своей личной информации, тогда как другие пользователи будут иметь доступ только к публичной информации?

Я попытался создать 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 , но как я могу получить доступ к своему пользователю и проверить разрешения в этом методе?

Решение:

Serializer:

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',
        ]

Viewset:

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 голосов
/ 28 июня 2018

Я думаю, это сделало бы всю магию :) 1001 *


 class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = PublicUserSerializer
    lookup_field = 'pk'
    authentication_classes = (FirebaseAuthentication,)

    <strike>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</strike>

    <b>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)</b>

UPDATE

Предложенный ответ 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)
0 голосов
/ 28 июня 2018

Вы бы использовали разрешения 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

Как только вы отделите свои наборы, вы можете настроить их логику.

...