KeyError в POST-запросе Django REST возникает только при отправке из frontend, но не при отправке из postman
Frontend
Это мой код во фронтенде. Вкратце, он получает запросы bing из стороннего api, перебирает результаты для создания нового массива и делает POST запрос к Django REST
axios
.get(
"exampleapi.bing.com/query",
{ withCredentials: true }
)
.then((response) => {
const webPages = response.data.webPages.value.map((page: any) => ({
id: nextId(),
documentId: draftId,
url: page.url,
title: page.name,
desc: page.snippet,
isNews: false,
}));
console.log('webPages: ', webPages);
axios
.post(
`${process.env.NEXT_PUBLIC_API_URL}/api/v1/recsources/`,
{
data: webPages,
},
{ withCredentials: true }
)
.catch(AxiosCatch);
})
.catch(AxiosCatch);
Вот что я вижу, когда я консольно регистрирую веб-страницы прямо перед тем, как сделать POST-запрос,
[
{
"id": "id19",
"documentId": "AVD4Mpy",
"url": "https://www.verywellmind.com/social-media-and-depression-5085354",
"title": "The Link Between Social Media and Depression - Verywell Mind",
"desc": "Studies also indicate that social media may trigger an array of negative emotions in users that contribute to or worsen their depression symptoms. Defining Depression Clinical depression or major depressive disorder is a mood disorder characterized by ongoing feelings of sadness and loss of interest in activities that an individual once enjoyed.",
"isNews": false
},
{
"id": "id20",
"documentId": "AVD4Mpy",
"url": "https://www.tuw.edu/school-news/does-social-media-cause-depression/",
"title": "Does Social Media Cause Depression? | Study Media Psychology",
"desc": "Recent research seems to link excessive social network usage to many mental health problems, including depression, anxiety, and low self-esteem. Social media also is associated with reduced attention span, sleep difficulties, and hyperactivity.",
"isNews": false
}
]
Затем, я получаю этот KeyError во время POST запроса, который, как я думаю, происходит потому, что сериализатор django не может прочитать поле "documntId" из данных запроса
File "/code/scraft-server/documents/serializers.py", line 59, in create
documentId = validated_data.pop("documentId")
KeyError: 'documentId'
Странно то, что выполнение POST-запроса с тем же webPages
в Postman работает без проблем. Он только отображает KeyError в фактическом коде typescript.
Backend
Это код для django REST:
models.py
class Document(models.Model):
id = HashidAutoField(primary_key=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=100, default="Untitled")
class RecSource(models.Model):
id = models.AutoField(primary_key=True)
document = models.ForeignKey(
Document,
related_name="rec_source_cards",
on_delete=models.CASCADE,
null=True,
blank=True,
)
documentId = models.CharField(max_length=50, default="docId", blank=True)
url = models.CharField(max_length=500, default="", blank=True)
title = models.CharField(max_length=500, default="", blank=True)
publisher = models.CharField(max_length=500, default="", blank=True)
desc = models.CharField(max_length=500, default="", blank=True)
isNews = models.BooleanField(default=False)
serializer.py
class RecSourceSerializer(serializers.ModelSerializer):
document = serializers.PrimaryKeyRelatedField(
pk_field=HashidSerializerCharField(source_field="documents.Document.id"),
read_only=True,
)
documentId = serializers.CharField(write_only=True, required=False)
class Meta:
model = RecSource
fields = "__all__"
def create(self, validated_data):
documentId = validated_data.pop("documentId")
recsource = RecSource.objects.create(
document=Document.objects.get(id=documentId), **validated_data
)
recsource.save()
return recsource
views.py
class RecSourceViewSet(viewsets.ModelViewSet):
queryset = RecSource.objects.all()
serializer_class = RecSourceSerializer
authentication_classes = (JSONWebTokenAuthentication,)
permission_classes = (IsRecSourceOwner,)
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(
data=request.data, many=isinstance(request.data, list)
)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(
serializer.data, status=status.HTTP_201_CREATED, headers=headers
)
Решил проблему, изменив код axios.post следующим образом:
axios
.post(
`${process.env.NEXT_PUBLIC_API_URL}/api/v1/recsources/`,
{
data: webPages,
},
{ withCredentials: true }
)
.catch(AxiosCatch);
К этому
axios
.post(
`${process.env.NEXT_PUBLIC_API_URL}/api/v1/recsources/`,
webPages
{ withCredentials: true }
)
.catch(AxiosCatch);