django vue 实战
django vue 实战
1. vue部分
1.1. 项目创建
创建vue项目
在django_vue项目根目录下,新建一个前端工程目录:
vue-init webpack frontend
奇怪的是win+R打开cmd命令行可以找到vue,在当前路径下打开cmd找不到vue
在创建项目的过程中会弹出一些与项目相关的选项需要回答,按照真实情况进行输入即可。
安装 vue 依赖模块
cd frontend
cnpm install
cnpm install vue-resource
cnpm install element-ui
django项目目录下新增frontend目录
此处是为了方便,一般前端项目与后端项目位于各自单独的代码仓库。
项目结构释义
在frontend目录src下包含入口文件main.js,入口组件App.vue等。后缀为vue的文件是Vue.js框架定义的单文件组件,其中标签中的内容可以理解为是类html的页面结构内容。
1.2. 代码编辑
在src/component文件夹下新建一个名为Home.vue的组件,通过调用之前在Django上写好的api,实现添加书籍和展示书籍信息的功能。在样式组件上我们使用了饿了么团队推出的element-ui,这是一套专门匹配Vue.js框架的功能样式组件。由于组件的编码涉及到了很多js、html、css的知识,并不是本文的重点,因此在此只贴出部分代码:
Home.vue文件代码:
<template>
<div class="home">
<el-row display="margin-top:10px">
<el-input v-model="input" placeholder="请输入书名" style="display:inline-table; width: 30%; float:left"></el-input>
<el-button type="primary" @click="addBook()" style="float:left; margin: 2px;">新增</el-button>
</el-row>
<el-row>
<el-table :data="bookList" style="width: 100%" border>
<el-table-column prop="id" label="编号" min-width="100">
<template slot-scope="scope"> {{ scope.row.pk }} </template>
</el-table-column>
<el-table-column prop="book_name" label="书名" min-width="100">
<template slot-scope="scope"> {{ scope.row.fields.book_name }} </template>
</el-table-column>
<el-table-column prop="book_author" label="作者" min-width="100">
<template slot-scope="scope"> {{ scope.row.fields.book_author }} </template>
</el-table-column>
<el-table-column prop="add_time" label="添加时间" min-width="100">
<template slot-scope="scope"> {{ scope.row.fields.add_time }} </template>
</el-table-column>
</el-table>
</el-row>
</div>
</template>
<script>
export default {
name: 'home',
data () {
return {
input: '',
bookList: []
}
},
mounted: function () {
this.showBooks()
},
methods: {
addBook () {
this.$http.get('http://127.0.0.1:9001/demo/add_book?book_name=' + this.input)
.then((response) => {
var res = JSON.parse(response.bodyText)
if (res.error_num === 0) {
this.showBooks()
} else {
this.$message.error('新增书籍失败,请重试')
console.log(res['msg'])
}
})
},
showBooks () {
this.$http.get('http://127.0.0.1:9001/demo/show_books')
.then((response) => {
var res = JSON.parse(response.bodyText)
console.log(res)
if (res.error_num === 0) {
this.bookList = res['list']
} else {
this.$message.error('查询书籍失败')
console.log(res['msg'])
}
})
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
在src/router目录的index.js中,把新建的Home组件,配置到vue-router路由中:
import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/components/Home'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'Home',
component: Home
}
]
})
在src/main.js文件中,导入element-ui、vue-resource库。
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import ElementUI from 'element-ui'
import VueResource from 'vue-resource'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)
Vue.use(VueResource)
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
跨域问题
因为端口不一,不同源,会出现跨域问题,需要在Django层注入header,用Django的第三方包django-cors-headers来解决跨域问题:
pip install django-cors-headers
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware', # cros 跨域 注意位置
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
CORS_ORIGIN_ALLOW_ALL = True
PS: 注意中间件的添加顺序。
1.3. 运行测试
前端项目frontend目录下,输入npm run dev启动node自带的服务器,访问
http://localhost:8080/#/
功能验证:
在默认的nodejs下方会出现书藉列表
新增书藉 vue项目实战 成功。新增的书籍信息会实时反映到页面的列表中,这得益于Vue.js的数据双向绑定特性。
PS:如果不启动django后端,前端获取不到项目并不会报错,只是列表为空;实际是前后端分别运行于不同server下。
2. 前端项目部署
在前端工程frontend目录下,执行
npm run build
如果项目没有错误的话,就能够看到所有的组件、css、图片等都被webpack自动打包到dist目录下了:
3. 整合Django和Vue.js前端
目前已经分别完成了Django后端和Vue.js前端部分,但实际上它们是运行在各自的服务器上。需要让Django直接使用相应的模板及静态文件。
找到project目录的urls.py,使用通用视图创建最简单的模板控制器,访问 『/』时直接返回 index.html:
# settings.py
# 声明扩展模板路径
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates'), os.path.join(BASE_DIR, 'frontend/dist')],
'APP_DIRS': True,
# 声明扩展静态文件路径
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "frontend/dist/static"),
]
# app_demo下的路由urls.py
urlpatterns = [
path(route='', view=views.index, name='index'),
path(route='hello/', view=views.hello, name='hello_page'),
path(r'f', view=views.index),
path('add/', view=views.add, name='add'),
path(r'ajax_list/', views.ajax_list, name='ajax_list'),
path(r'ajax_dict/', views.ajax_dict, name='ajax_dict'),
path('add_book', views.add_book),
path('show_books', views.show_books),
path(r'show', TemplateView.as_view(template_name='index.html'))
]
访问http://127.0.0.1:9001/demo/show#/
结果正常

浙公网安备 33010602011771号