1. Front-end preparation
First create a new project, then introduce the iView plug-in, configure router npm to install iView
npm install iview --save cnpm install iview --save
src/main.js file content
import Vue from 'vue' import App from './App.vue' import router from './router' import iView from 'iview'; import 'iview/dist/styles/iview.css'; Vue.use(iView); Vue.config.productionTip = false new Vue({ router, render: h => h(App) }).$mount('#app')
src/router.js file content
import Vue from 'vue' import Router from 'vue-router' Vue.use(Router) export default new Router({ routes: [ { path: '/table1', component: () => import('./views/table1.vue') }, { path: '/table2', component: () => import('./views/table2.vue') }, { path:'/', redirect:'/table1' } ] })
2. Backend preparation
Environmental description
python version: 3.6.6 Django version: 1.11.8 Database: MariaDB 5.5.60
New Django project, new app in the project, well-configured database
Content of api_test/app01/models.py file
from django.db import models class UserProfile(models.Model): name = models.CharField("User name", max_length=32) email = models.EmailField(max_length=32) status = models.IntegerField(default=1) def to_dic(self): return dict([(attr, getattr(self, attr)) for attr in [f.name for f in self._meta.fields]])
Content of api_test/urls.py file
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^update_user/$',views.update_user), url(r'^get_user/$',views.get_user_list), ]
api_test/app01/views.py file content
from django.http import JsonResponse from django.views.decorators.csrf import csrf_exempt from .models import UserProfile @csrf_exempt def update_user(request): request_dict = json.loads(request.body) user_id = request_dict.get("user_id") name = request_dict.get("name") email = request_dict.get("email") status = request_dict.get("status") try: UserProfile.objects.filter(id=int(user_id)).update(name=name, email=email, status=status) return JsonResponse({"result": True}) except Exception as e: return JsonResponse({"result": False}) def get_user_list(request): # For I in range (1,1001): // / Create 1000 records to the database # name = "user" + str(i) # email = "user%s@qq.com" % str(i) # status = random.randint(1, 3) # user_obj = UserProfile(name=name, email=email, status=status) # user_obj.save() current = request.GET.get("current", 1) size = request.GET.get("size", 0) sortType = request.GET.get("sortType") filterType = request.GET.get("filterType") res_list = [] try: user_list = UserProfile.objects.all() if filterType and filterType != "undefined": user_list = user_list.filter(status=int(filterType)) total = user_list.count() if current and size: end = int(current) * int(size) start = (int(current) - 1) * int(size) user_list = user_list[start:end] except Exception as e: print(e) return JsonResponse({"result": False}, safe=False) for user in user_list: res_list.append(user.to_dic()) if sortType == "desc": res_list = sorted(res_list, key=lambda x: x["id"], reverse=True) else: res_list = sorted(res_list, key=lambda x: x["id"], reverse=False) res = { "data": { "list": res_list, "total": total }, "result": True } return JsonResponse(res, safe=False)
Here, when the front-end sends POST requests to the back-end, the back-end does not perform csrftoken validation. The front-end obtains csrftoken, and the back-end does not validate csrftoken in this example.
3. Editable cells
src/views/table1.vue file content
<template> <div style="padding:32px 64px"> <h1>Editable cells</h1> <Table :columns="columns" :data="data" :loading="loading" border size="small"> </Table> <div style="text-align:center;margin:16px 0"> <Page :total="total" :current.sync="current" show-total @on-change="getData"></Page> </div> </div> </template> <script> import axios from 'axios' export default { data() { return { columns:[ { type:"index", width:100, align:'center', title:'ID', key:'id', }, { title:'User name', key:'name', render: (h, {row, index}) => { let edit; let control; if (this.editIndex === index) { edit = [h('Input', { props: { value: row.name }, on: { input: (val) => { this.editValue = val; } } })]; control = [ h('Icon', { style: { cursor: 'pointer', margin: '8px' }, props: { type: 'md-checkmark', size: 16, color: '#19be6b' }, on: { click: () => { this.data[index].name = this.editValue; this.editIndex = -1; axios.post(`http://127.0.0.1:8000/update_user/`,{ user_id: row.id, name: this.editValue, email: row.email, status: row.status }).then(res => { if(res.data.result) { this.$Message.success('Successful modification of username'); } else { this.$Message.error('request was aborted'); } }) } } }), h('Icon', { style: { cursor: 'pointer', margin: '8px' }, props: { type: 'md-close', size: 16, color: '#ed4014' }, on: { click: () => { this.editIndex = -1; } } }) ] } else { edit = row.name; control = [h('Icon', { style: { cursor: 'pointer' }, props: { type: 'ios-create-outline', size: 16 }, on: { click: () => { this.editIndex = index; this.editValue = row.name; } } })] } return h('Row', [ h('Col', { props: { span: 16 } }, edit), h('Col', { props: { span: 6 } }, control) ]) } }, { title:'state', key:'status', render: (h, {row}) => { if (row.status === 1) { return h('Tag', { props: { color: 'green' } }, "Level 1") } else if (row.status === 2) { return h('Tag', { props: { color: 'red' } }, "Level 2") } else if (row.status === 3) { return h('Tag', { props: { color: 'blue' } }, "Level 3") } }, }, { title:'mailbox', key:'email', } ], data:[], loading:false, total:0, editIndex: -1, editValue: '', current:1, // Current page size:10, // Set the number of data bars that can be displayed initially per page } }, methods:{ getData (){ if (this.loading) return; this.loading = true; axios.get(`http://127.0.0.1:8000/get_user/?current=${this.current}&size=${this.size}`).then(res => { if(res.data.result) { this.data = res.data.data.list; this.total = res.data.data.total; this.loading = false } else { this.$Message.error('request was aborted'); } }) }, handleChangeSize (val){ this.size = val; this.$nextTick(() => { this.getData(); }) } }, mounted () { this.getData(); } } </script>
Start the front-end and back-end respectively. Open the URL with the browser: http://localhost:8080/#/table1. Render the page as follows
Click on the modification button after a row of usernames, and the original data of the username will be input box, allowing the user to enter the modification data.
When the user completes the modification and clicks save, the modified user name will be sent to the back-end interface and saved to the database.
Refresh the browser again and you will see that the user name has been changed
3. Editable rows
src/views/table2.vue file content
<template> <div style="padding:32px 64px"> <h1>Editable line</h1> <Table :data="data" :columns="column" border></Table> <div style="text-align:center;margin:16px 0"> <Page :total="total" :current.sync="current" :page-size-opts="page_size_array" show-sizer show-total @on-change="getData" @on-page-size-change="handleChangeSize"></Page> </div> </div> </template> <script> import axios from 'axios' export default { data() { return { editIndex: -1, editName: '', editEmail: '', editStatus: '', statusArray: [ { key: '1', value: '1' }, { key: '2', value: '2' }, { key: '3', value: '3' }, ], column: [ { type:"index", width:100, align:'center', title:'ID', key:'id', }, { title: "User name", key: 'name', render: (h, {row, index}) => { let edit; if (this.editIndex === index) { this.editName = row.name edit = [h('Input', { props: { value: row.name }, on: { input: (val) => { this.editName = val; } } })] } else { edit = row.name; } return h('div', [edit]); } }, { title: "mailbox", key: 'email', render: (h, {row, index}) => { let edit; if (this.editIndex === index) { this.editEmail = row.email edit = [h('Input', { props: { value: row.email }, on: { input: (val) => { this.editEmail = val; } } })] } else { edit = row.email; } return h('div', [edit]); } }, { title: "Grade", key: 'status', render: (h, {row, index}) => { let edit; if (this.editIndex === index) { this.editStatus = row.status let options = this.statusArray.map(v => { return h('Option',{ props: { value: v.value } }, v.key) }) edit = [h('Select', { props: { value: row.status }, on: { input: (val) => { this.editStatus = val; } } },options)] } else { edit = row.status; } return h('div', [edit]); } }, { title: "operation", render: (h, {row, index}) => { if (this.editIndex === index) { return [ h('Button', { props: { type: 'success' }, on: { click: () => { this.data[index].name = this.editName; this.data[index].email = this.editEmail; this.data[index].status = this.editStatus; this.editIndex = -1; axios.post(`http://127.0.0.1:8000/update_user/`,{ user_id: row.id, name: this.editName, email: this.editEmail, status: this.editStatus }).then(res => { if(res.data.result) { this.$Message.success('Successful modification of username'); } else { this.$Message.error('request was aborted'); } }) } } }, 'Preservation'), h('Button', { props: { type: 'error' }, style: { marginLeft: '6px' }, on: { click: () => { this.editIndex = -1; } } }, 'cancel') ] } else { return h('Button', { on: { click: () => { this.editName = row.name; this.editAge = row.age; this.editAddress = row.address; this.editIndex = index; } } }, 'modify') } } } ], data: [], loading:false, page_size_array: [10, 20, 30, 40, 60, 100], // Set the number of switchable items per page total:0, current:1, // Current page size:10, // Set the number of data bars that can be displayed initially per page }; }, methods:{ getData (){ if (this.loading) return; this.loading = true; axios.get(`http://127.0.0.1:8000/get_user/?current=${this.current}&size=${this.size}`).then(res => { if(res.data.result) { this.data = res.data.data.list; this.total = res.data.data.total; this.loading = false } else { this.$Message.error('request was aborted'); } }) }, handleChangeSize (val){ this.size = val; this.$nextTick(() => { this.getData(); }) } }, mounted () { this.getData(); } } </script>
Open the URL with a browser: http://localhost:8080/#/table2, rendering the page as follows
Click on the modification button in one line of operation bar, the original data of user name and mailbox will be input box, the original data in input box will be original data, and the original data of grade will be changed into select drop-down box for users to choose.
When the user changes and clicks save, the modified user information will be sent to the back-end interface through the POST request and saved to the database.
Refresh the browser again and you will see that the user name has been changed