我们将学习使用 Django REST Framework 在 Django 后端和 React js 前端之间进行通信的过程。为了更好地理解这个概念,我们将构建一个简单的任务管理器,并介绍 React js 和 Django 之间这种类型的集成的主要概念。
对于这个项目,React 将作为前端,通过对 Django 后端的请求处理用户界面(UI)。
前端(React js):
现在让我们为 Todo 应用程序构建前端。为此,请按照以下步骤操作:
步骤 1:
导航到主项目目录(即 Django-react-app)并使用以下命令激活虚拟环境:
dar\脚本\activate.bat
第 2 步:
现在使用以下命令创建 React js 应用程序的样板:
npx create-react-app frontend
这里,npx 代表节点包可执行文件。设置样板后,您将收到以下消息:
我们还需要一些 UI 风格来进行 UI 设计,特别是Reactstrap和Bootstrap。
步骤3:
因此,使用以下命令在项目中安装reactstrap和bootstrap:
npm install Reactstrap init
第 4 步:
首先进入 Frontend 文件夹并使用以下命令运行 React 服务器,以确保到目前为止一切正常:
npm start
如果一切正常,您将在 localhost:3000 上看到以下页面
第5步:
现在打开前端文件夹中的App.js文件。并清除样板代码并将其更改为以下代码
import "./App.css";
function App() {
return <div className="App"><h2>Welcome to Geeksforgeeks!</h2></div>;
}
export default App;
此时前端将如下所示:
正如您在上图中看到的。对 App.js 文件所做的任何更改都会直接反映到 UI。
第 6 步:
现在将代码添加到App.js 文件中。为了更好地理解,在代码中添加了注释。
// import Component from the react module
import React, { Component } from "react";
import Modal from "./components/Modal";
import axios from 'axios';
// create a class that extends the component
class App extends Component {
// add a constructor to take props
constructor(props) {
super(props);
// add the props here
this.state = {
// the viewCompleted prop represents the status
// of the task. Set it to false by default
viewCompleted: false,
activeItem: {
title: "",
description: "",
completed: false
},
// this list stores all the completed tasks
taskList: []
};
}
// Add componentDidMount()
componentDidMount() {
this.refreshList();
}
refreshList = () => {
axios //Axios to send and receive HTTP requests
.get("http://localhost:8000/api/tasks/")
.then(res => this.setState({ taskList: res.data }))
.catch(err => console.log(err));
};
// this arrow function takes status as a parameter
// and changes the status of viewCompleted to true
// if the status is true, else changes it to false
displayCompleted = status => {
if (status) {
return this.setState({ viewCompleted: true });
}
return this.setState({ viewCompleted: false });
};
// this array function renders two spans that help control
// the set of items to be displayed(ie, completed or incomplete)
renderTabList = () => {
return (
<div className="my-5 tab-list">
<span
onClick={() => this.displayCompleted(true)}
className={this.state.viewCompleted ? "active" : ""}
>
completed
</span>
<span
onClick={() => this.displayCompleted(false)}
className={this.state.viewCompleted ? "" : "active"}
>
Incompleted
</span>
</div>
);
};
// Main variable to render items on the screen
renderItems = () => {
const { viewCompleted } = this.state;
const newItems = this.state.taskList.filter(
(item) => item.completed === viewCompleted
);
return newItems.map((item) => (
<li
key={item.id}
className="list-group-item d-flex justify-content-between align-items-center"
>
<span
className={`todo-title mr-2 ${
this.state.viewCompleted ? "completed-todo" : ""
}`}
title={item.description}
>
{item.title}
</span>
<span>
<button
onClick={() => this.editItem(item)}
className="btn btn-secondary mr-2"
>
Edit
</button>
<button
onClick={() => this.handleDelete(item)}
className="btn btn-danger"
>
Delete
</button>
</span>
</li>
));
};
toggle = () => {
//add this after modal creation
this.setState({ modal: !this.state.modal });
};
// Submit an item
handleSubmit = (item) => {
this.toggle();
alert("save" + JSON.stringify(item));
if (item.id) {
// if old post to edit and submit
axios
.put(`http://localhost:8000/api/tasks/${item.id}/`, item)
.then((res) => this.refreshList());
return;
}
// if new post to submit
axios
.post("http://localhost:8000/api/tasks/", item)
.then((res) => this.refreshList());
};
// Delete item
handleDelete = (item) => {
alert("delete" + JSON.stringify(item));
axios
.delete(`http://localhost:8000/api/tasks/${item.id}/`)
.then((res) => this.refreshList());
};
// Create item
createItem = () => {
const item = { title: "", description: "", completed: false };
this.setState({ activeItem: item, modal: !this.state.modal });
};
//Edit item
editItem = (item) => {
this.setState({ activeItem: item, modal: !this.state.modal });
};
// Start by visual effects to viewer
render() {
return (
<main className="content">
<h1 className="text-success text-uppercase text-center my-4">
GFG Task Manager
</h1>
<div className="row ">
<div className="col-md-6 col-sm-10 mx-auto p-0">
<div className="card p-3">
<div className="">
<button onClick={this.createItem} className="btn btn-info">
Add task
</button>
</div>
{this.renderTabList()}
<ul className="list-group list-group-flush">
{this.renderItems()}
</ul>
</div>
</div>
</div>
{this.state.modal ? (
<Modal
activeItem={this.state.activeItem}
toggle={this.toggle}
onSave={this.handleSubmit}
/>
) : null}
</main>
);
}
}
export default App;
第7步:
现在打开Index.css文件,清除其中的CSS并在文件中添加以下CSS:
.todo-title {
cursor: pointer;
}
.completed-todo {
text-decoration: line-through;
}
.tab-list > span {
padding: 5px 8px;
border: 1px solid rgb(7, 167, 68);
border-radius: 10px;
margin-right: 5px;
cursor: pointer;
}
.tab-list > span.active {
background-color: rgb(6, 139, 12);
color: #fff;
}
第8步:
现在在src目录中创建一个名为“Components”的新文件夹,并向其中添加一个文件Modal.js。然后将以下代码添加到其中。
import React, { Component } from "react";
// importing all of these classes from reactstrap module
import {
Button,
Modal,
ModalHeader,
ModalBody,
ModalFooter,
Form,
FormGroup,
Input,
Label
} from "reactstrap";
// build a class base component
class CustomModal extends Component {
constructor(props) {
super(props);
this.state = {
activeItem: this.props.activeItem
};
}
// changes handler to check if a checkbox is checked or not
handleChange = e => {
let { name, value } = e.target;
if (e.target.type === "checkbox") {
value = e.target.checked;
}
const activeItem = { ...this.state.activeItem, [name]: value };
this.setState({ activeItem });
};
// rendering modal in the custommodal class received toggle and on save as props,
render() {
const { toggle, onSave } = this.props;
return (
<Modal isOpen={true} toggle={toggle}>
<ModalHeader toggle={toggle}> Task Item </ModalHeader>
<ModalBody>
<Form>
{/* 3 formgroups
1 title label */}
<FormGroup>
<Label for="title">Title</Label>
<Input
type="text"
name="title"
value={this.state.activeItem.title}
onChange={this.handleChange}
placeholder="Enter Task Title"
/>
</FormGroup>
{/* 2 description label */}
<FormGroup>
<Label for="description">Description</Label>
<Input
type="text"
name="description"
value={this.state.activeItem.description}
onChange={this.handleChange}
placeholder="Enter Task Description"
/>
</FormGroup>
{/* 3 completed label */}
<FormGroup check>
<Label for="completed">
<Input
type="checkbox"
name="completed"
checked={this.state.activeItem.completed}
onChange={this.handleChange}
/>
Completed
</Label>
</FormGroup>
</Form>
</ModalBody>
{/* create a modal footer */}
<ModalFooter>
<Button color="success" onClick={() => onSave(this.state.activeItem)}>
Save
</Button>
</ModalFooter>
</Modal>
);
}
}
export default CustomModal
第10步:
对index.js文件进行如下更改:
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
// importing css stylesheet to use the bootstrap class
// add this line only in this file
import "bootstrap/dist/css/bootstrap.min.css";
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById("root")
);
API连接:
为了向 Django 后端服务器上的 API 端点发出请求,我们需要安装Axios。在 frontend 文件夹中使用以下命令来安装 Axios:
npm install axios
输出:
恭喜!!. 至此,您已经成功构建了一个Fullstack Django-React应用程序,并使用Django REST框架建立了前端和后端之间的通信。