使用 Django Rest Framework 构建的后端 Json 在前端以某种方式未定义,使用 React 构建

Posted

技术标签:

【中文标题】使用 Django Rest Framework 构建的后端 Json 在前端以某种方式未定义,使用 React 构建【英文标题】:Json from backend which is built with Django Rest Framework is somehow undefined at frontend, built with React 【发布时间】:2021-04-10 05:40:09 【问题描述】:

我目前正在尝试通过构建一个简单的待办事项应用程序来学习 Django Rest Framework 和 React.js 的集成,前者用于后端,后者用于前端。

views.py

from rest_framework import viewsets
from . import models
from .serializers import ToDoSerializer, ToDoContainerSerializer

class ToDoContainerViewSet(viewsets.ModelViewSet):

    queryset = models.ToDoContainer.objects.all().order_by('created')
    serializer_class = ToDoContainerSerializer

序列化器.py

from rest_framework.serializers import HyperlinkedModelSerializer
from . import models as todo_model
from rest_framework.serializers import ReadOnlyField

class ToDoContainerSerializer(HyperlinkedModelSerializer):
    created_by = ReadOnlyField(source='created_by.id')

    class Meta:
        model = todo_model.ToDoContainer
        fields = (
            'url', 'id',
            'created_by',
            'todos_name',
            'todos_important',
            'todos_items_count',
        )
        extra_kwargs = 
            'url': 
                'view_name': 'todos:todocontainer-detail',
            ,
        

models.py

from django.db import models
from core.models import TimeStampedModel
from django.core.validators import MinValueValidator, MaxValueValidator

class ToDoContainer(TimeStampedModel):

    created_by = models.ForeignKey(
        user_model.User, on_delete=models.CASCADE, related_name="todo_container")
    todos_name = models.CharField(max_length=50)
    todos_important = models.BooleanField(default=False)

    def todos_items_count(self):
        todo_items = len(self.todo.all())
        return int(todo_items)

    def __str__(self):
        return str(self.todos_name)

我像上面那样构建了视图、序列化程序、模型,并且看起来像下面这样正确生成了 api。

我尝试通过使用如下 axios 模块将上述的 json 获取到前端。

import React from 'react';
import axios from 'axios';
import ToDoCard from './ToDoCard';

class ToDoLists extends React.Component 
    state = 
        isLoading: true,
        toDos: []
    ;
    getToDos = async () => 
        const  results  = await axios.get("/backend/todos-api/todo_container.json");
        console.log(results) //Errors here, 'results' is undefined
        this.setState( toDos: results, isLoading: false )
    
    componentDidMount() 
        this.getToDos();
    
    render() 
        const  isLoading, toDos  = this.state;
        return (<section className="container">
            isLoading ? (
                <div className="loader">
                    <span className="loader__text">Loading...</span>
                </div>
            ) : (
                    <div className="toDos">
                        
                            toDos.map(toDo => 
                                return <ToDoCard
                                    key=toDo.id
                                    id=toDo.id
                                    todos_name=toDo.todos_name
                                    todos_important=toDo.todos_important
                                />
                            )
                        
                    </div>
                )
            
        </section>)
    


export default ToDoLists;

但是来自'axios.get("/backend/todos-api/todo_container.json");'的'结果'未定义,尽管后端看起来很好,如下所示。

django 结果

[04/Jan/2021 20:38:07] "GET /backend/todos-api/todo_container.json HTTP/1.1" 200 372

我还设置了如下设置并尝试了'axios.get("/backend/todos-api/todo_container/");'但结果是一样的。 “结果”未定义,后端似乎很好。

settings.py

REST_FRAMEWORK = 
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 10,
    'DEFAULT_RENDERER_CLASSES': (
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer'
    ),
    'DEFAULT_PARSER_CLASSES': (
        'rest_framework.parsers.JSONParser',
        'rest_framework.parsers.FormParser',
        'rest_framework.parsers.MultiPartParser'
    )


CORS_ORIGIN_WHITELIST = (
    'https://localhost:3000',
    'https://127.0.0.1:3000',
)

django 结果

[04/Jan/2021 20:32:13] "GET /backend/todos-api/todo_container/ HTTP/1.1" 200 364

我应该怎么做才能解决这个问题?

【问题讨论】:

【参考方案1】:

我相信您应该在网址中添加附加 ?format=json 而不是 .json。除非您将 url 更改为专门的“.json”。但奇怪的是你得到了来自两者的200 回复:

 "/backend/todos-api/todo_container.json" 

"/backend/todos-api/todo_container/" 

你能发布你的 urls.py 吗?

也尝试更改为,因为您正在解包对象,我认为 axios 响应中没有名为 results 的字段,但有 data 这是实际的 json:

const  data  = await axios.get("/backend/todos-api/todo_container/");

【讨论】:

非常感谢!你的回答对我有用!!我将 'results' 更改为 'data' ,axios 终于收到了 json 对象。此外,我需要稍微修复 react 子组件。最后它奏效了!再次非常感谢您的帮助!

以上是关于使用 Django Rest Framework 构建的后端 Json 在前端以某种方式未定义,使用 React 构建的主要内容,如果未能解决你的问题,请参考以下文章

Django Rest Framework 和 django Rest Framework simplejwt 两因素身份验证

18-Django REST framework-使用Django开发REST 接口

如何在 django-rest-framework 中为 API 使用 TokenAuthentication

Django-rest-framework 和 django-rest-framework-jwt APIViews and validation Authorization headers

django rest framework中文介绍

使用 django-rest-framework-simplejwt 注册后返回令牌