skip to Main Content

I’m developing a React application that retrieves a user’s followings from my Django backend API. However, I’m facing issues where the followings data is not being returned correctly.

API Response

When I make a GET request to the endpoint http://127.0.0.1:8000/api/chat/landing/, I receive a JSON response structured like this:

{
    "current_followings": [
        {
            "id": 1,
            "username": "Amir",
            "email": "[email protected]",
            "full_name": "amirali",
            "profile_photo": "/media/profile_photo/1000_F_244376003_1smlBNfWYSInMDUFymPuCcms6d1mOqaF_oU9kIP0.jpg",
            "banner_photo": "/media/banner_photo/header.jpg",
            "phone": null,
            "address": "",
            "bio": "",
            "profile_views": 1
        }
    ],
    ...
}

The response includes an array of current_followings, each containing various fields like id, username, full_name, and profile_photo.

Django views.py

The view that handles this request is defined as follows:

from rest_framework.views import APIView
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from .models import Follower, BasicUserProfile  # Assuming these are defined elsewhere

class ChatLandingView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        try:
            current_basic_user_profile = get_current_user_profile(request, User, BasicUserProfile)
            current_followings = Follower.objects.filter(follower=current_basic_user_profile).select_related('following')

            followings_serializer = BasicUserProfileSerializer([f.following for f in current_followings], many=True)

            data = {
                "current_followings": followings_serializer.data,
                ...
            }

            return Response(data, status=status.HTTP_200_OK)

        except ObjectDoesNotExist:
            return Response({"error": "Object not found"}, status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

This view checks for authenticated users and fetches their followings using the Follower model. It serializes the followings data before sending it back in the response.

React Code

In my React component, I’m using React Query to fetch the followings data:

import React from 'react';
import { useQuery } from '@tanstack/react-query';
import axios from 'axios';

const getToken = () => localStorage.getItem('authToken');

const fetchFollowings = async () => {
    const token = getToken();
    if (!token) {
        throw new Error("No authentication token found. Please log in.");
    }

    const response = await axios.get('http://127.0.0.1:8000/api/chat/landing/', {
        headers: { 'Authorization': `Bearer ${token}` },
    });

    return response.data.current_followings;
};

const ChatLanding = () => {
    const { data: followings = [], error, isLoading } = useQuery({
        queryKey: ['followings'],
        queryFn: fetchFollowings,
    });

    return (
        <div>
            <h2>Your Followings</h2>
            {isLoading && <p>Loading...</p>}
            {error && <p>{error.message}</p>}
            {followings.length === 0 && !isLoading && !error && (
                <p>No followings found.</p>
            )}
            {followings.length > 0 && (
                <ul>
                    {followings.map(following => (
                        <li key={following.id}>
                            <img src={following.profile_photo} alt={following.full_name} />
                            <p>{following.full_name} ({following.username})</p>
                        </li>
                    ))}
                </ul>
            )}
        </div>
    );
};

export default ChatLanding;

Issue

  • The current_followings array is not rendering correctly in my React component. Instead, I sometimes receive an error related to the authentication token.
  • I’ve verified that the token is being correctly stored and retrieved in the client-side code.
  • When I check the console, I can see the API response is coming back successfully with a status of 200.

Question

What could be causing the issue with the followings not rendering as expected? Are there any adjustments I should make to either the Django view or the React code to resolve this?

Any insights would be greatly appreciated!

2

Answers


  1. Chosen as BEST ANSWER

    The issue was caused by an incorrect use of the serializer for the current_followings data. In the original code, the serializer was incorrectly applied to a list of BasicUserProfile objects, which was causing issues when trying to return the list of followings in the response.

    Here's how the problem was solved:

    1. Correct Handling of current_followings: The current_followings variable was obtained using Follower.objects.filter(follower=current_basic_user_profile), but the data needed to be properly serialized before returning. Instead of serializing the entire Follower objects, we needed to serialize the following field, which contains the user profiles being followed.

    2. Proper Use of select_related: To optimize the query, select_related was used on the following field to avoid additional database queries when accessing the related user profiles. This ensures that the following user profiles are fetched along with the Follower object, improving performance.

    3. Updated Serializer Application: The BasicUserProfileSerializer was used correctly to serialize the following user profiles rather than serializing the Follower model itself.

    Updated Code:

    class ChatLandingView(APIView):
        permission_classes = [IsAuthenticated]
    
        def get(self, request):
            try:
                current_basic_user = get_current_user(request, User)
                current_basic_user_profile = get_current_user_profile(request, User, BasicUserProfile)
                topics_to_follow = get_topics_to_follow(Topic, ObjectDoesNotExist, random)
                who_to_follow = get_who_to_follow(BasicUserProfile)
    
                # Adjusted field names based on your Follower model
                current_followings = Follower.objects.filter(follower=current_basic_user_profile).select_related('following')
    
                # Serialize the data
                user_serializer = BasicUserProfileSerializer(current_basic_user_profile)
                topics_serializer = TopicSerializer(topics_to_follow, many=True)
                followings_serializer = BasicUserProfileSerializer([f.following for f in current_followings], many=True)
                who_to_follow_serializer = BasicUserProfileSerializer(who_to_follow, many=True)
    
                data = {
                    "current_basic_user": user_serializer.data,
                    "current_basic_user_profile": user_serializer.data,
                    "who_to_follow": who_to_follow_serializer.data,
                    "topics_to_follow": topics_serializer.data,
                    "current_followings": followings_serializer.data,
                }
    
                return Response(data, status=status.HTTP_200_OK)
    
            except ObjectDoesNotExist:
                return Response({"error": "Object not found"}, status=status.HTTP_404_NOT_FOUND)
            except Exception as e:
                return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    

    Key Fixes:

    1. Serialization of following Profiles:

      • Instead of serializing the Follower object, we serialized the following field (f.following), which is the actual user profile that is being followed.
      • This is done using the line:
        followings_serializer = BasicUserProfileSerializer([f.following for f in current_followings], many=True)
        
    2. Database Query Optimization with select_related:

      • The select_related('following') is used in the query to fetch the following user profiles in the same database query, ensuring efficient access to the related user data.

    Result:

    The updated code correctly returns a list of user profiles that the current user is following. The current_followings field now returns the serialized data of the users being followed, and the response structure is appropriately formatted.


  2. Token is being stored correctly and properly attached to the headers. What you are missing is the authentication_classes at your view:

    views.py

    class ChatLandingView(APIView):
        authentication_classes = [TokenAuthentication]
        ...
    

    Although, I am not sure what kind of authentication package you have in place. Just be sure that the Authentication prefix is also correct.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search