Django 的特点是有强大的数据库功能和自带的强大的后台功能,但是模板系统又没有目前比较流行的 React / Vue 强大,接下来就告诉大家如何搭建一个 Django + Vue 单页面应用的开发环境,以及 Django 和 Vue 的数据交互、以及 vue-resource 的配置。
如果你不想搭建单页面应用,想使用 Django 的模板系统 + Vue 的混合体,文章底部也介绍了使用方法
开发环境配置
教程非常简单,几步就搞定了:
假设你的电脑已经安装了 Git, Node,
- 首先偷个懒,直接克隆一个库 hello-vue-django
https://github.com/zaxlct/hello-vue-django
- 需要执行的命令全都写在了
Makefile
里,所以按照 README 里描述的执行一下就好:
make dev
make migrate
make run
- 浏览器打开
localhost:8000
就能看到正确的页面了
基本原理
一共启动了两个服务,Django 启动了 8000 的端口,WebpackDevServer 启动了 8001 端口,每次frontend
目录下的文件发生变化, django-webpack-loader
插件都会把文件映射到 backend
的 templates/index.html
里。
templates/index.html
我们一般不会改动它,前端的代码全部都会写在frontend
目录下。所以我们也就放弃了 Django 自带的模板系统。
项目开发完毕也不需要任何转移文件操作,只需要:
make prod
make build
P.s. Makefile to make your life easy :)
Vue 和 Django 数据交互
假设 views.py 里有这么一段代码:
def index(request):
return render(request, 'index.html', {
'test': 123
})
那么 App.vue 里可以这样拿到数据吗:
{{test}}
答案是不可能的,我们是单页面应用,放弃了 Django 自带的模板系统, Django 的数据只能通过 Ajax 传递给 App.vue。
vue-resource 配置
以前我们都是用 jquery 封装过的 Ajax 方法,但是 vue-resource 和 Vue 更配哦!
首先安装 vue-resource
npm install vue-resource --save
POST 请求时,Django 默认加了 CSRF 验证,我们可以在 cookie 里拿到这个 csrftoken
,然后再配置一下 vue-resource ,这样每次发送 POST 请求时都会自动带上 csrftoken 了:
import VueResource from 'vue-resource'
Vue.use(VueResource)
// 取 cookie
function getCookie(name) {
let arr,
reg=new RegExp("(^| )"+name+"=([^;]*)(;|$)")
if(arr=document.cookie.match(reg)) {
return decodeURIComponent(arr[2])
}
}
// 设置 POST 请求时 的 data 格式
Vue.http.options.emulateJSON = true
// 设置 X-CSRFToken
Vue.http.interceptors.push(function(request, next) {
request.method = 'POST'
request.headers.set('X-CSRFToken', getCookie('csrftoken'))
next()
})
POST 请求代码实例
// 在 vue 模板文件里
new Vue({
data() {
return {
name: '隔壁老王' ,
age: '38',
}
},
methods: {
fetch() {
this.$http.post(this.URL, this.data).then(res => {
// do something
},res => {
// do sonmething
})
}
}
})
Django 的模板系统 + Vue 的混合体配置
Django 模板与Vue 的变量都是使用{{ }}
包裹起来的,在渲染 Django 模板时会先替代掉所有的{{ }}
及被包裹在其中的内容,使得 Vue 没有使用 {{ }}
来绑定变量。
方法一
我们可以改一下 Vue 的配置,使用两个中括号[[ ]]
来代替。
new Vue({
el: '#app',
delimiters: ['[[', ']]'],
}}
方法二
禁用 Django 模板渲染,Django 标签 verbatim
可以使包裹其中的代码不进行渲染保持原样输出:
{% verbatim %}
{{ vue }}
{% endverbatim %}
我们可以在需要用于 Vue 的地方使用 {% verbatim %} {% endverbatim %}
包裹。
字典和数组传递到 JS 里
Django 如果想直接把字典、数组传递到到 JS 里 ,需要要这么接收数据,否则 JS 会报错
def index(request):
return render(request, 'index.html', {
'list': [{'age': 18}, 200],
'obj': {'name': '隔壁老王'}
})
最后
这种简单的单页面应用架构做个小项目足够用了,但是如果是中型或者大型项目,还是得用类似 Django-RESTful-framework
等解决方案。
如果该文章帮助到了您,请赏个赞:)