djangodjango-rest-frameworkdjango-serializerdjango-rest-authdjango-select-related

How can I return all the fields related to user model when user login?


I want to show all the related to user model field as the user logins in response in a apiview.

Views .py code

class UserLoginView(APIView):
    renderer_classes = [UserRenderer]

    def post(self, request, format=None):
        serializer = UserLoginSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        email = serializer.data.get('email')
        password = serializer.data.get('password')
        user = authenticate(email=email, password=password)
        if user is not None:
            if Profile.objects.filter(user=user).first().is_verified:
                token = get_tokens_for_user(user)
                # profile = user.profile.all()
                # pbys = user.propertiesbystreet.all()
                # pbyb = user.propertiesbyblocks.all()
                return Response({'msg': 'Login Success', 'data': serializer.data, 'token': token}, status=status.HTTP_200_OK)
            else:
                return Response({'msg': 'Account is not verified'}, status=status.HTTP_404_NOT_FOUND)
        else:
            return Response({'errors': {'non_field_errors': ['Email or Password is not Valid']}}, status=status.HTTP_404_NOT_FOUND)

Serializers class from serializer.py

class UserLoginSerializer(serializers.ModelSerializer):
    email = serializers.EmailField(max_length=255)
    userdata = UserDetailsSerializers(read_only=True)

    class Meta:
        model = User
        fields = ['email', 'password',  'userdata']


Solution

  • The problem is in the used serializer:

    class UserLoginSerializer(serializers.ModelSerializer):
        email = serializers.EmailField(max_length=255)
        userdata = UserDetailsSerializers(read_only=True)
    

    This type of serializer requires a relation (user to user) and it's not your case.

    So to return the related fields for the user model in the response of the UserLoginView view, you can include those fields in the UserDetailsSerializers serializer and then include the serializer in the UserLoginSerializer as a nested serializer.

    For example, you can define the UserDetailsSerializers serializer like this:

    class UserDetailsSerializers(serializers.ModelSerializer):
        class Meta:
            model = User
            fields = ['id', 'first_name', 'last_name', 'email', 'is_staff', ...]
    

    Then, in the UserLoginView view, you can include the userdata field in the response data like this:

    class UserLoginView(APIView):
            renderer_classes = [UserRenderer]
        def post(self, request, format=None):
            serializer = UserLoginSerializer(data=request.data)
            serializer.is_valid(raise_exception=True)
            email = serializer.data.get('email')
            password = serializer.data.get('password')
            user = authenticate(email=email, password=password)
            if user is not None:
                if Profile.objects.filter(user=user).first().is_verified:
                    token = get_tokens_for_user(user)
                    user_data = UserDetailsSerializers(user).data
                    return Response({'msg': 'Login Success', 'data': serializer.data, 'token': token, 'user_data': user_data}, status=status.HTTP_200_OK)
                else:
                    return Response({'msg': 'Account is not verified'}, status=status.HTTP_404_NOT_FOUND)
            else:
                return Response({'errors': {'non_field_errors': ['Email or Password is not Valid']}}, status=status.HTTP_404_NOT_FOUND)
    

    This will include the related fields for the user model in the response data under the user_data key.

    Or you can just replace data with usser_data if you dont need the initial data

    return Response({'msg': 'Login Success', 'data': user_data, 'token': token}, status=status.HTTP_200_OK)