javascript - 无法使用 Reactjs fetch() 方法向 Django REST API 发送 PUT 请求
问题描述
我最近开始学习 Reactjs 并制作了一个简单的 Todo react 应用程序,以便一步一步地学习它。这个 Todo react 前端中的数据来自一个简单的 Todo Django REST API。但问题是我想改变“完成”的状态来描述一个任务完成。我试图通过使用唯一的“id”向 API 发送 PUT 请求来做到这一点,但出现了一些错误。以下是我的方法:
List.js
import React from 'react'
import Todo from './Todo'
import Nav from './Nav'
//Class based Component
class List extends React.Component {
constructor() {
super()
this.state = {
todos: [],
}
this.handleChange = this.handleChange.bind(this)
}
fetchData() {
fetch('http://localhost:8000/Todo-api/')
.then(response => response.json())
.then((data) => {
this.setState({
todos: data
});
});
}
componentDidMount() {
this.fetchData();
}
handleChange(id) {
this.setState(prevState => {
const updatedData = prevState.todos.map(todo => {
if (todo.id === id) {
todo.completed = !todo.completed
}
return todo
})
return {
todos: updatedData
}
})
fetch(`http://127.0.0.1:8000/Todo-api/${id}/?format=json/`,
{
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Accept' : 'application/json',
// Other possible headers
},
body: JSON.stringify(this.state)
}).then(function (response) {
return response.json();
}).then(function (data) {
console.log("Data is ok", data);
}).catch(function (ex) {
console.log("parsing failed", ex);
});
}
currentDate() {
return new Date().getFullYear();
}
render() {
const Data = this.state.todos.map(details => <Todo key={details.id} det={details} handleChange={this.handleChange} />)
const someStyle = {
marginTop: "40px", marginLeft: "100px", marginRight: "100px",
}
console.log(this.state.todos)
return (
<div>
<Nav />
<div className="todo-list box">
{Data}
</div>
<hr style={someStyle} />
<p className="text-center" style={{ fontFamily: "Roboto Mono", lineHeight: 0.5 }}>Copyright ©️ {this.currentDate()} Parth Pandya </p>
<p className="text-center" style={{ fontFamily: "Roboto Mono", fontSize: 10, lineHeight: 0.5 }}>Some rights reserved.</p>
</div>
)
}
}
export default List
Todo.js
import React from 'react'
function Todo(props) {
const completeStyles = {
fontStyle: "italic",
textDecoration: "Line-through",
color: "gray",
}
return (
<div className="todo-item">
<input type="checkbox" onChange={() => props.handleChange(props.det.id)} checked={props.det.completed} />
<p style={props.det.completed ? completeStyles : null}>{props.det.title}</p>
</div>
);
}
export default Todo;
API的views.py
from django.shortcuts import render
from rest_framework.response import Response
from rest_framework import status
from rest_framework.views import APIView
from .serializers import TodoDataSerializer
from .models import TodoData
# Create your views here.
class Todolist(APIView):
serializer_class = TodoDataSerializer
def get(self, request):
ToDoData = TodoData.objects.all()
serializer = TodoDataSerializer(ToDoData, many=True)
return Response(serializer.data)
def post(self, request):
serializer = TodoDataSerializer(data=request.data)
if(serializer.is_valid()):
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.data, status=status.HTTP_404_BAD_REQUEST)
class TodoDetail(APIView):
serializer_class = TodoDataSerializer
def get(self, request, pk):
ToDoData = TodoData.objects.get(pk=pk)
serializer = TodoDataSerializer(ToDoData)
return Response(serializer.data)
def delete(self, request, pk):
ToDoData = TodoData.objects.filter(pk=pk)
ToDoData.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
def put(self, request, pk):
snippets = TodoData.objects.get(pk=pk)
serializer = TodoDataSerializer(snippets, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
DELETE 方法效果很好,但我不知道如何为 PUT/POST 执行此操作。浏览了许多资源,但其中大多数都建议axios
我现在不想使用。我想使用fetch()
.
当我使用时,body:JSON.stringify(this.state.todos)
我收到以下错误:
PUT http://127.0.0.1:8000/Todo-api/4/ 400 (Bad Request) Data is ok {non_field_errors: Array(1)}non_field_errors: ["Invalid data. Expected a dictionary, but got list."]__proto__: Object
当我使用时,body:JSON.stringify(this.state)
我收到以下错误:
PUT http://127.0.0.1:8000/Todo-api/4/ 400 (Bad Request) Data is ok {title: Array(1), completed: Array(1)} completed: ["This field is required."] title: ["This field is required."] __proto__: Object
现在要做什么?
(注意:要在本地测试它,请克隆此git 存储库)
解决方案
请尝试使用PATCH
而不是PUT
.
PUT
用于完整对象更新,PATCH
用于部分更新(您只能更新选定的字段)。
你需要的是PATCH
.
在更新请求中,请仅发送带有您要更新的字段({“status”:“complete”})并id
在请求 URL 中设置的 dict。
更重要的是,您可以在我的文章中查看完整的工作 CRUD 示例:Django Rest Framework 和 React 中的 CRUD。
推荐阅读
- swift - 您是否能够跨不同的视图控制器/.swift 文件检索存储在 UserDefaults 中的数据?
- beautifulsoup - 使用 BS4 和请求发送不和谐嵌入的产品库存解析表单 HTML
- discord - PokeCord 旁边的绿条是怎么做的?
- php - 在数组PHP中组合两个随机数
- scala - 如何根据配方中“应用”成分的另一序列减少每种单独的成分
- vba - 在 Access 表单上添加“新按钮”选项
- python - QApplication 在第二个进程的非主线程中使用 pyQt4:这段代码是否合法,如果不合法,为什么它有效?
- java - 比较每一轮for循环的值?
- javascript - 从 for 循环创建字符串值
- c# - C# 控制台代码有问题。试图获得一个while循环来平均3个测试分数。最终产品仅使用在 while 循环中输入的第一个数字