0%

Vue + Django

写在开头:
1看这里的时候,请确保你已将熟悉JavaScript以及了解Vue的语法, Django的语法也略懂一二。
如果不是很了解,请点击这里查看学习文档VueDjango,否则下文可能有些不好理解。
2文章有点长 ,因为包含了一个Index.vue页面。
3第一次写长文章,所以排版很尴尬,请指正。

  1. 安装Vue环境
  2. 安装element-ui组件 使用其组件美化界面
1
npm i element-ui -S ||  npm install element-ui --save
1
2
3
4
5
main.js 
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';

Vue.use(ElementUI)
  1. 安装axios 使用其完成前端到后端的请求

由于axios 使用Vue.use(无效),所以要将其绑定在Vue原型上

1
npm install axios --save |  brew install axios --save
1
2
3
4
5
import axios from 'axios'

axios.defaults.baseURL = 'http://localhost:8000'

Vue.prototype.$axios = axios
  1. 安装Django及配置环境
  2. 配置mysql数据库,使用sqlite3的 跳过此步骤无需配置
1
2
3
4
5
6
7
8
9
10
11
settings.py
DATABASES = {
'default': { #
'ENGINE': 'django.db.backends.mysql', # 不同库有不同的殷勤
'NAME': 'python_use', # 使用的库名
'USER': 'root',
'PASSWORD': '',
'HOST': '127.0.0.1',
'PORT': '3306',
}
}

配置完成后请查看django是否报错,不报错即连接成功

  1. 安装 pipdjango-cors-headers
1
2

pip install django-cors-headers
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
settings.py

INSTALLED_APPS = {
...
'corsheaders',
...
}


MIDDLEWARE = [
...

'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
...
]


CORS_ORIGIN_ALLOW_ALL = True





至此,已将Vue和Django安装并配置好,接下来写一个简单的CRUD操作。
请确认你的整个项目目录与此类似

![](Vue + Django/2064404-d3a828d4530715b4.png)

项目目录结构

以下使用的目录均为此图所示


  1. 配置路由
1
2
3
4
5
first/urls.py 
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'', include('crud.urls')),
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
crud/urls.py




from django.conf.urls import url
from . import views

urlpatterns = [
url('create/', views.create, name = 'create'),
url('read', views.read, name = 'read'),
url('update/', views.update, name = 'update'),
url('delete/', views.delete, name = 'delete'),
url('search', views.search, name = 'search')
]
  1. 创建models,即在数据库中创建表
1
2
3
4
5
from django.db import models
class Books ( models.Model ):
book_name = models.CharField( max_length = 255 )
book_price = models.DecimalField( max_digits = 5, decimal_places = 2 )
book_time = models.DateTimeField( '保存日期', auto_now_add = True )

Models创建完成后运行命令 将其应用到数据库中并创建表
如果不懂 请返回顶部阅读Django文档

1
2
python manage.py makemigrations
python manage.py migrate
  1. 编写views.py 完成增删改查的逻辑
1
2
3
4
5
6
7
8
9
10
11
12
# 1 获取前端传递来的参数
# 1.1 get方法发送的参数
request.GET['content']
# 1.2 post方法发送的参数
obj = json.loads(request.body)
name = obj['name']
# 2 由于使用Books.objects下的方法,获取到的数据为Query Set类型,
# 所以需要使用serializers.serialize("json", books)
# 将查询到的数据进行序列化,变成可读的对象。
# 3 向前端返回处理结果
return HttpResponse(json.dumps(res), content_type="application/json")
# 将res变成json字符串返回给前端。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91

from __future__ import unicode_literals
from django.shortcuts import render
from django.http import HttpResponse
import json
from django.core import serializers
from django.utils import timezone
from crud.models import Books

def search(request):
content = request.GET['content']
try:
books = serializers.serialize("json",Books.objects.filter(book_name__contains=content))
res = {
"code": 200,
"data": books
}
print(books)
except Exception,e:
res = {
"code": 0,
"errMsg": e
}
return HttpResponse(json.dumps(res), content_type="application/json")

def create(request):
print('create')
obj = json.loads(request.body)
name = obj['name']
price = obj['price']
try:
book = Books(book_name=name, book_price=price, book_time=timezone.now())
book.save()
res = {
"code": 200,
}
except Exception,e:
res = {
"code": 0,
"errMsg": e
}
return HttpResponse(json.dumps(res), content_type="application/json")

def read(request):
print('read')
try:
res = {
"code": 200,
"data": serializers.serialize("json",Books.objects.filter())
}
except Exception,e:
res = {
"code": 0,
"errMsg": e
}
return HttpResponse(json.dumps(res), content_type="application/json")

def update(request):
print('update')
obj = json.loads(request.body)
pid = obj['id']
name = obj['name']
price = obj['price']
try:
Books.objects.filter(id=pid).update(book_price=price, book_name=name)
res = {
"code": 200
}
except Exception,e:
res = {
"code": 0,
"errMsg": e
}
return HttpResponse(json.dumps(res), content_type="application/json")

def delete(request):
print('delete')
obj = json.loads(request.body)
print(obj)
pid = obj['id']
try:
Books.objects.filter(id=pid).delete()
res = {
"code": 200
}
except Exception,e:
res = {
"code": 0,
"errMsg": e
}
return HttpResponse(json.dumps(res), content_type="application/json")

  1. 配置路由
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
frontend/src/router/index.js

import Vue from 'vue'
import Router from 'vue-router'
import Index from '@/components/Index'

Vue.use(Router)

export default new Router({
routes: [
{
path: '/',
name: 'index',
component: Index
}
]
})
  1. 编写路由中使用到的组件 与上面import所用名称和路径需要一致,请耐心看完注释。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21








this.$axios.get('/search', {
params: {
content: this.search
}
}).then(res => {
console.log(res)
})
this.$axios.post('/delete/', JSON.stringify(row)).then(res => {

console.log(res)


})

以下为Index.vue的全部页面,包含增删改查的基本操作,以及更改和新增时的弹出框:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
frontend/src/components/Index.vue
<template>
<div>
<el-button type="primary" round @click="handleShowCreate">增加书籍</el-button>
<el-input v-model="search" placeholder="请输入内容" style="width: 200px" @keyup.enter.native="handleSearch"/>
<el-button type="primary" round @click="handleSearch">搜索</el-button>
<el-table :data="booksData" height="250" border style="width: 600px; margin: 40px auto;" v-loading="loading">
<el-table-column
prop="book_name"
label="书名"
align="center"
width="200">
</el-table-column>
<el-table-column
prop="book_price"
label="价格"
align="center"
width="200">
</el-table-column>
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<el-button
size="mini"
@click="handleUpdate(scope.$index, scope.row)">编辑</el-button>
<el-button
size="mini"
type="danger"
@click="handleDelete(scope.$index, scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-dialog title="修改书籍" :visible.sync="dialogUpdateVisible">
<el-form :model="updateData">
<el-form-item label="书籍名称">
<el-input auto-complete="off" v-model="updateData.name"></el-input>
</el-form-item>
<el-form-item label="书籍价格">
<el-input-number v-model="updateData.price" :precision="2" :step="0.01" :max="9999"></el-input-number>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="handleCancel('dialogUpdateVisible')">Cancel</el-button>
<el-button type="primary" @click="handleConfirm('dialogUpdateVisible')">Submit</el-button>
</div>
</el-dialog>
<el-dialog title="增加书籍" :visible.sync="dialogCreateVisible">
<el-form :model="createData">
<el-form-item label="书籍名称">
<el-input auto-complete="off" v-model="createData.name"></el-input>
</el-form-item>
<el-form-item label="书籍价格">
<el-input-number v-model="createData.price" :precision="2" :step="0.01" :max="9999"></el-input-number>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="handleCancel('dialogCreateVisible')">Cancel</el-button>
<el-button type="primary" @click="handleCreate('dialogCreateVisible')">Submit</el-button>
</div>
</el-dialog>
</div>
</template>

<script>
export default {
name: 'index',
data () {
return {
search: '',
booksData: [],
oldData: {},
updateData: {},
createData: {
name: '',
price: 0
},
dialogUpdateVisible: false,
dialogCreateVisible: false,
loading: true
}
},
methods: {
handleShowCreate () {
this.dialogCreateVisible = true
},
handleCreate () {
if (this.createData.name === '') {
this.$message.error('please input book name')
return
}
if (this.createData.price === 0) {
this.$message.error('please input book price')
return
}
this.$axios.post('/create/', JSON.stringify(this.createData)).then(res => {
if (res.data.code === 200) {
this.$message.success(`create ${this.createData.name} success`)
this.dialogCreateVisible = false
this.handleRead()
} else {
this.$message.error("can't read books database")
}
})
console.log(this.createData)
},
handleRead () {
this.booksData = []
this.$axios.get('/read').then(res => {
this.loading = false
if (res.data.code === 200) {
let books = JSON.parse(res.data.data)
for (let i in books) {
books[i].fields.id = books[i].pk
books[i].fields.book_price = Number(books[i].fields.book_price)
this.booksData.push(books[i].fields)
}
console.log(this.booksData)
} else {
this.$message.console.error("can't read books database")
}
}).catch((res) => {
console.log(res)
})
},
handleUpdate (index, row) {
this.dialogUpdateVisible = true
this.updateData = Object.assign({}, {
id: row.id,
name: row.book_name,
price: row.book_price,
time: row.book_time
})
this.oldData = Object.assign({}, {
id: row.id,
name: row.book_name,
price: row.book_price,
time: row.book_time
})
},
handleDelete (index, row) {
this.$confirm(`are you sure to delete ${this.updateData.name} ?`, '', {
confirmButtonText: 'submit',
cancelButtonText: 'cancel',
type: 'warning'
}).then(() => {
this.$axios.post('/delete/', JSON.stringify(row)).then(res => {
if (res.data.code === 200) {
this.$message.success(`delete ${this.updateData.name} success`)
this.handleRead()
} else {
this.$message.error("can't read books database")
}
})
}).catch(() => {
this.$message.info('cancel delete')
})
},
handleCancel (arg) {
this.$message.info('cancel')
this[arg] = false
},
handleConfirm (arg) {
if (this.updateData.name === this.oldData.name && this.updateData.price === this.oldData.price) {
this.$message.error('please update something or cancel')
return
}
this[arg] = false
this.$axios.post('/update/', JSON.stringify(this.updateData)).then(res => {
if (res.data.code === 200) {
this.$message.success(`update ${this.updateData.name} success`)
this.handleRead()
} else {
this.$message.error("can't read books database")
}
})
},
handleSearch () {
this.$axios.get('search', {
params: {
content: this.search
}
}).then(res => {
if (res.data.code === 200) {
if (res.data.data && JSON.parse(res.data.data).length > 0) {
this.booksData = []
let books = JSON.parse(res.data.data)
for (let i in books) {
let obj = {
id: books[i].pk,
book_name: books[i].fields.book_name,
book_price: Number(books[i].fields.book_price),
book_time: books[i].fields.book_time
}
this.booksData.push(obj)
}
} else {
this.$message.error(`can't search contains of '${this.search}' in database`)
}
} else {
this.$message.error(`can't search books in database`)
}
})
}
},
mounted () {
this.handleRead()
}
}
</script>

到这里,一个增删改查基本操作的页面就写完了,如果哪里有问题可以留言指正。 git源码以上传, 没事可以star/fork 更新将在以下附注后增加。

https://github.com/RogersLei/django-vue


附注 :

  1. Vue添加事件所用到的修饰符:

    ![](Vue + Django/2064404-1aa984b701bf3e11.png)

    Vue事件绑定修饰符

  2. Django中模糊查询用到的语法:

YourModels.objects.filter(headline__contains=str)
字段名__contains / __icontains 忽略大小写

更多精彩内容,就在简书APP

“小礼物走一走,来简书关注我”

还没有人赞赏,支持一下

总资产23共写了2.2W字获得33个赞共22个粉丝

推荐阅读更多精彩内容

  • 一.前言 最近接手了一个项目,后端是django,前端是django自带的模板,用的是jinja2,写了一段时间发…

  • 组织文章借鉴 ——培训师的21项修炼 书籍结构:错误的案例情景重现-抛出问题,传道受业解惑也 我们假设一个场景,大…

  • 每天总是忙忙碌碌,感觉时间完全不够用,更不要说是学习了,可是忙忙碌碌到最后感觉收获也很小,就像大家说的,瞎忙活。…

  • 和姑姑聊起当时借钱给已故父亲治病时的场景,我依稀记得当时我和涛古,妈妈给厂里老板下跪借那三万块的场景。这辈子希望以…