Please click to read the previous article
1. Requirements description
This article takes the student information query function as an example, adopts a front-end and back-end separation architecture, the back-end provides a RESTFul interface, and the front-end code is implemented with Vue.js + Bottstrap.
1.1 This example requires the following query functions:
List query, single query
Add student information
Change student information
Delete student information
1.2 According to the REST interface guidelines, the RESTFul style API is designed as follows
Before starting, it is recommended to read REST Interface Fundamentals
operate | request type | resource request url | request data |
---|---|---|---|
list query | GET | http://127.0.0.1:8000/student/ | none |
single query | GET | http://127.0.0.1:8000/student/1/ | none |
add record | POST | http://127.0.0.1:8000/student/2/ | {‘name’:‘Jack’, ‘no’:‘A001’,…} |
amend record | PUT | http://127.0.0.1:8000/student/2/ | {‘name’:‘Jack’, ‘no’:‘B001’,…} |
Delete Record | DELETE | http://127.0.0.1:8000/student/2/ | none |
The above interface has been implemented by django-rest-framework.
2. Front-end design
Technology stack:
- Vue.js dynamic data update
- Bootstrap5 is responsible for rendering
- Axios is responsible for interface communication
interface design:
- Display multiple pieces of data in tabular form;
- Provide modify and delete buttons for each row of records
- The page provides an add button
- The page provides query function
- All functions are completed on a single page.
Actual page test:
display all records,
query a single piece of data ,
add data,
modify data, click the "Modify" button, a modification bar will pop up, after updating, click the "Submit" button
to delete, just click the delete button
3. Complete code
All code is placed in 1 file, vue_student.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - Vue router(runoob.com)</title>
<link href="https://cdn.staticfile.org/twitter-bootstrap/5.1.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.staticfile.org/twitter-bootstrap/5.1.1/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script>
<script src="https://cdn.staticfile.org/vue-router/2.7.0/vue-router.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div class="container mt-2">
<div class="row my-2 mx-2 ">
<div class="col-md-10 p-3">
<h2 class="text-center">学生信息查询</h2>
<div id='app'>
<div class="container mt-3">
<div class="row">
<div class="col-md-6">
<input type='number' v-model="sid" placeholder='请输入学生id'>
<button v-on:click="searchInfo" class="btn btn-primary" >查询</button>
</div>
<div class="col-md-6 d-flex flex-row-reverse">
<button class="btn btn-info" v-on:click="addReq">添加学生</button>
</div>
</div>
</div>
<div class="row my-2 border border-1 border-primary shadow-sm py-2 mx-2" v-if="isShowDataDiv">
<div class="form-group row">
<label for="stdid" class="col-md-1 col-form-label" >ID</label>
<div class="col-md-2"><input type="text" class="form-control" v-model="studentInfo.id" id="stdid" readonly="true"></div>
<label for="stdname" class="col-md-1 col-form-label">姓名</label>
<div class="col-md-2"><input type="text" class="form-control" v-model="studentInfo.name" id="stdname"></div>
<label for="stdno" class="col-md-1 col-form-label">学号</label>
<div class="col-md-2"><input type="text" class="form-control" v-model="studentInfo.no" id='stdno' ></div>
<div class='col-md-3 mt-2'>
<span>性别: </span>
<input type="radio" id="male" value=0 v-model="studentInfo.gender">
<label for="runoob" >男</label>
<input type="radio" id="female" value=1 v-model="studentInfo.gender">
<label for="google">女</label>
</div>
</div>
<div class="form-group row">
<label for="stdage" class="col-md-1 col-form-label">年龄</label>
<div class="col-md-2"><input type="number" class="form-control" v-model="studentInfo.age" id="stdage"></div>
<label for="stdclass" class="col-md-1 col-form-label">班级</label>
<div class="col-md-2"><input type="text" class="form-control" v-model="studentInfo.class_name" id="stdclass"></div>
<label for="stdscore" class="col-md-1 col-form-label">成绩</label>
<div class="col-md-2"><input type="number" class="form-control" v-model="studentInfo.score" id="stdscore"></div>
<div class="col-md-3 d-flex flex-row-reverse" v-if="isShowUpgradeBtn"><button class="btn btn-outline-primary" v-on:click="upgradeConfirm">更新提交</button></div>
<div class="col-md-3 d-flex flex-row-reverse" v-if="isShowAddBtn"><button class="btn btn-outline-primary" v-on:click="addConfirm">添加提交</button></div>
</div>
</div>
<table class="table table-striped">
<thead>
<tr>
<td>ID</td>
<td>姓名</td>
<td>学号</td>
<td>性别</td>
<td>年龄</td>
<td>班级</td>
<td>成绩</td>
<td>操作</td>
</tr>
</thead>
<tbody>
<tr v-for="(student,index) in studentArray">
<td v-text="student.id"></td>
<td v-text="student.name"></td>
<td v-text="student.no"></td>
<td v-text="student.gender"></td>
<td v-text="student.age"></td>
<td v-text="student.class_name"></td>
<td v-text="student.score"></td>
<td> <button class='btn btn-primary btn-sm' v-on:click="upgradeReq(student.id,index)">修改</button> <button class='btn btn-danger btn-sm' v-on:click="deleteStudent(student.id,index)">删除</button></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<script>
const url = "http://127.0.0.1:8000/student/v1/";
var array_index;
var vm = new Vue({
el: '#app',
data: {
studentInfo: {
id: 1,
name:'王小乙',
no: 'B0001',
gender: 0,
age: 14,
class_name: '初2',
score: 80
},
studentArray: [],
sid: 1,
isShowDataDiv: false,
isShowAddBtn: false,
isShowUpgradeBtn: true
},
methods: {
searchInfo: function(){
that = this;
let url_req = url
if(that.sid > 0){
url_req = url+String(that.sid)+'/';
}
axios.get(url_req)
.then( function(response){
console.log(response.data);
that.studentArray=[]
if (response.data instanceof Array){
for (var n in response.data){
that.studentArray.push(response.data[n]);
}
}
else if (response.data instanceof Object ){
that.studentArray.push(response.data);
}
})
.catch(function (error) {
// 请求失败处理
console.log(error);
})
},
addData: function(){
this.studentArray.push(this.studentInfo);
},
deleteStudent: function(pk,index){
that = this;
url_req = url+pk+'/';
axios.delete(url_req)
.then(function(response){
console.log(response.status);
that.studentArray.splice(index,1)
})
.catch(function(err){
console.log(err)})
},
addStudent: function(){
window.open("vue_student_add.html");
},
addReq: function(){
that=this;
that.studentInfo = {
id: 0,
name:'',
no: '',
gender: 0,
age: 0,
class_name: '2',
score: 0
}
that.isShowDataDiv=true;
that.isShowUpgradeBtn=false;
that.isShowAddBtn=true;
},
addConfirm: function(){
that=this;
if (that.studentInfo.name !='' && that.studentInfo.no!='' ) {
axios.post(url,that.studentInfo)
.then(function(response){
console.log(response);
alert("添加成功")
that.isShowDataDiv=false;
that.isShowUpgradeBtn=true;
that.isShowAddBtn=false;
that.studentArray.push(that.studentInfo)
})
.catch(function(err){
console.log(err);
})
}
else {
alert("姓名,学号不能为空")
}
},
upgradeReq: function(pk,index){
that = this;
that.studentInfo = that.studentArray[index];
array_index = index;
that.isShowDataDiv=true;
that.isShowUpgradeBtn=true;
that.isShowAddBtn=false;
// alert("update data " + pk)
},
upgradeConfirm: function(){
that = this;
url_req = url+that.studentInfo.id+'/';
axios.put(url_req,that.studentInfo)
.then(response=>{
console.log(response.status);
that.studentArray[array_index]=that.studentInfo;
alert("更新成功")
that.isShowDataDiv=false;
})
.catch(function(err){
console.log(err)})
}
}
});
vm.addData()
</script>
</body>
</html>
Running in a test environment usually encounters CORS cross-domain problems, causing requests sent by Axios to be blocked. For solutions, please refer to my other blog post Django Solve CORS cross-domain problems .
Summarize
Advantages and disadvantages of DRF+Vue.js or DRF+React front-end and back-end separation architecture
The advantage of adopting DRF+Vue.js or DRF+React front-end and back-end separation architecture is that it can develop front-end pages with better user experience, but the premise is that front-end engineers must join the project, or you can learn and master Javascript + Vue technology yourself . Of course, mastering these two tools will also improve your ability. In addition, separating the front-end and back-end projects will generally increase the amount of code and testing workload for some projects.