Запрос React не возвращает данные из API Django
Я разрабатываю приложение React, которое извлекает данные о подписчиках пользователя из бэкенд API Django. Однако я столкнулся с проблемой, когда данные о подписчиках возвращаются некорректно.
API Response
Когда я делаю GET-запрос к конечной точке http://127.0.0.1:8000/api/chat/landing/
, я получаю JSON-ответ, структурированный следующим образом:
{
"current_followings": [
{
"id": 1,
"username": "Amir",
"email": "Amir@amir.ir",
"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
}
],
...
}
Ответ включает массив current_followings
, каждый из которых содержит различные поля, такие как id
, username
, full_name
и profile_photo
.
Django views.py
Представление, которое обрабатывает этот запрос, определено следующим образом:
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)
Это представление проверяет наличие аутентифицированных пользователей и извлекает данные об их следовании, используя модель Follower
. Оно сериализует данные следования перед отправкой их обратно в ответ.
Код реакции
В моем компоненте React я использую React Query для получения следующих данных:
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;
Выпуск
- Массив
current_followings
не отображается корректно в моем компоненте React. Вместо этого я иногда получаю ошибку, связанную с маркером аутентификации. - Я проверил, что токен правильно хранится и извлекается в коде на стороне клиента.
- Когда я проверяю консоль, я вижу, что ответ API успешно возвращается со статусом 200.
Вопрос
Что может быть причиной того, что представление не отображается так, как ожидалось? Есть ли какие-либо изменения, которые я должен внести в представление Django или в код React, чтобы решить эту проблему?
Любые соображения будут высоко оценены!
Токен хранится правильно и правильно прикрепляется к заголовкам. Вам не хватает authentication_classes
в представлении:
views.py
class ChatLandingView(APIView):
authentication_classes = [TokenAuthentication]
...
Хотя я не уверен, какой пакет аутентификации у вас установлен. Просто убедитесь, что префикс Authentication
также корректен.
Проблема была вызвана неправильным использованием сериализатора для данных current_followings
. В исходном коде сериализатор был неправильно применен к списку объектов BasicUserProfile
, что вызывало проблемы при попытке вернуть в ответ список следования.
Вот как была решена эта проблема:
Корректная обработка
current_followings
: Переменнаяcurrent_followings
была получена с помощьюFollower.objects.filter(follower=current_basic_user_profile)
, но перед возвратом данные нужно было правильно сериализовать. Вместо того чтобы сериализовать весь объектFollower
, нам нужно было сериализовать полеfollowing
, содержащее профили пользователей, за которыми ведется наблюдение.Правильное использование
select_related
: Для оптимизации запроса в полеselect_related
было использованоfollowing
, чтобы избежать дополнительных запросов к базе данных при обращении к связанным профилям пользователей. Это гарантирует, что профили пользователейfollowing
будут получены вместе с объектомFollower
, что повышает производительность.Обновленное приложение сериализатора: Сериализатор
BasicUserProfileSerializer
правильно использовался для сериализацииfollowing
профилей пользователей, а не для сериализации самойFollower
модели.
Обновленный код:
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)
Ключевые исправления:
Сериализация
following
профилей:- Вместо того чтобы сериализовать объект
Follower
, мы сериализовали полеfollowing
(f.following
), которое является фактическим профилем пользователя, за которым ведется наблюдение. - Это делается с помощью строки:
followings_serializer = BasicUserProfileSerializer([f.following for f in current_followings], many=True)
- Вместо того чтобы сериализовать объект
Оптимизация запросов к базе данных с помощью
select_related
:- В запросе используется
select_related('following')
, чтобы получитьfollowing
профили пользователей в том же запросе к базе данных, обеспечивая эффективный доступ к связанным данным о пользователях.
- В запросе используется
Результат:
Обновленный код корректно возвращает список профилей пользователей, за которыми следит текущий пользователь. Поле current_followings
теперь возвращает сериализованные данные пользователей, за которыми следят, а структура ответа отформатирована соответствующим образом.