python django + vue 前后端分离
部署环境:
安装python环境,安装python3: https://www.python.org/downloads/
安装 django:
pip install django
使用淘宝的cnpm替代npm,安装cnpm:
npm install -g cnpm --registry=https://registry.npm.taobao.org
构建项目:使用命令新建django项目:
django-admin startproject projectname
进入projectname目录,新建应用:
python manage.py startapp base_app
在项目的settings中更改数据库(所以,者须如果需要更改就需要安装mysql)
DATABASES = {
'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
'ENGINE': 'django.db.backends.mysql',
'NAME': 'supertrampaidb',
'HOST': 'localhost',
'PORT': 3306,
'USER': 'root',
'PASSWORD': 'root',
}
}
把新建的app加入到settings INSTALLED_APPS中
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'base_app',
]
在app的models.py 中创建model,并映射到数据库中映射命令:
class Book(models.Model):
book_name = models.CharField(max_length=64)
add_time = models.DateTimeField(auto_now_add=True)
def __unicode__(self):
return self.book_name
python manage.py makemigrations base_app
python manage.py migrate
在views.p中编写接口代码:
@require_http_methods(['GET'])
def add_book(request):
response = {}
try:
book = Book(book_name=request.GET.get('book_name'))
book.save()
response['msg'] = 'success'
response['code'] = 200
except Exception as e:
response['msg'] = str(e)
response['code'] = 500
return JsonResponse(response)
@require_http_methods(['GET'])
def show_books(reuqest):
response = {}
try:
books = Book.objects.filter()
response['list'] = json.loads(serializers.serialize('json', books))
response['msg'] = 'success'
response['code'] = 200
except Exception as e:
response['msg'] = str(e)
response['code'] = 500
return JsonResponse(response)
在应用目录下,新建urls.py文件,把接口添加到路由里面
from django.conf.urls import url
from base_app import views
urlpatterns = [
url(r'add_book$', views.add_book, ),
url(r'show_books$', views.show_books, ),
]
在项目的urls文件中,中应用的urls添加进去。
urlpatterns = [
path('admin/', admin.site.urls),
url(r'^api/', include(base_app.urls)),
url(r'^$', TemplateView.as_view(template_name='index.html')),
]
启动服务:
python manage.py runserver
在postman通过如下url测试接口:
127.0.0.1:8000/api/add_book?book_name=bookname
1127.0.0.1:8000/api/show_books
vue项目:
安装vue-cli
cnpm install -g vue-cli
在项目projectname中创建前端工程:
vue-init webpack vueappname
进入vueappname目录,安装vue的node依赖:
1. cnpm install
2. cnpm install vue-resource
3. cnpm element-ui
在src/component文件家下新建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 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="queryBook()" 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 scope="scope"> {{ scope.row.pk }} </template>
</el-table-column>
<el-table-column prop="book_name" label="书名" min-width="100">
<template scope="scope"> {{ scope.row.fields.book_name }} </template>
</el-table-column>
<el-table-column prop="add_time" label="添加时间" min-width="100">
<template scope="scope"> {{ scope.row.fields.add_time }} </template>
</el-table-column>
<el-table-column prop="add_time" label="删除" min-width="100">
<el-button type="primary" @click="delBook()" style="float:left; margin: 2px;">删除</el-button>
</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:8000/api/add_book?book_name=' + this.input)
.then((response) => {
var res = JSON.parse(response.bodyText)
if (res.code === 200) {
this.showBooks()
} else {
this.$message.error('新增书籍失败,请重试')
console.log(res['msg'])
}
})
},
showBooks () {
this.$http.get('http://127.0.0.1:8000/api/show_books')
.then((response) => {
var res = JSON.parse(response.bodyText)
console.log(res)
if (res.code === 200) {
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
}
]
})
依赖第三方包解决跨域问题:
pip install django-cors-headers
在project settingspy中
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware',
'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
另开启一个terminal 启动 :npm run dev 自带的服务器
构建前端工程:npm run build
整合前后端:
项目的settings.py 文件的TEMPLATES .dirs=vueappname/dist
默认DIRS为空
'DIRS': ['base_vue/dist'],
增加:项目的settings.py 文件下:
配置静态文件的路径
Add for vuejs
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "base_vue/dist/static"),
]
运行项目:python manage.py runserver
一路上遇到的坑:
在前端工程目录下,执行:cnpm run build
构建完成以后,报错:
问题: Tip: built files are meant to be served over an HTTP server.
Opening index.html over file:// won't work.
解决:npm install -g http-server
问题:
DateTimeField、DateField和TimeField三种类型可以用来创建日期字段,其值分别对应着datetime()、date()、time()三种对象。这三个field有着相同的参数auto_now和auto_now_add,在实际使用中很容易出错
问题:pip install django socket.timeout: The read operation timed out
解决 pip --default-timeout=100 install django
问题:django.core.exceptions.ImproperlyConfigured: mysqlclient 1.3.13 or newer is required; you have 0.9.3
解决:在项目的__init__.py 文件中无需配置(可能是以前版本的问题,导致需要增加该配置,现在版本迭代,因此无需增加)
问题:django.core.exceptions.ImproperlyConfigured: mysqlclient 1.3.13 or newer is required; you have 0.9.3
解决:在项目的__init__.py 文件中无需配置(可能是以前版本的问题,导致需要增加该配置,现在版本迭代,因此无需增加)
问题:AttributeError: module 'django.forms.forms' has no attribute 'ModelForm'
解决: from django import forms # a
from django.forms import Form # b
在导入模块时,如果有a,b这种情况的需要分开导入。
问题:AttributeError: 'LoginForm' object has no attribute 'cleaned_data'
解决:如果在XXXForm中获取了*个字段,在html页面也需要填写这么的字段,否则form.is_valid()==False
提示:出现form.is_valid()返回false的原因一般是form中的每个field默认都是required的,如果没有填,form.is_valid()就会返回false。另外,html中的form中的各个field的name一定要和对应的form类的各个field的name保持一致,这也是一个易错点。
问题:请问如果一个SQL带IN语句。例如:select count() from Table1 where Column1 in (a,b,c) and ..;想要使用动态SQL语句,(a,b,c) 为绑定变量,括号内元素个数不确定。请问要如何编写这个动态SQL语句?
解决:select count() from Table1 where FIND_IN_SET('Column1','1,2,3,4')
问题:~~~SyntaxError: invalid syntax File "manage.py", line 16 ) from exc ~~~
解决:python2 不是使用python manage.py startapp appname 新建应用,而是使用其他的命令,在lz 的机子上,因为安装cnpm自动安装了p2,所以,把p2卸载即可

浙公网安备 33010602011771号