功能类似于:
一,安装及简单配置前端vue开发环境与项目
1,下载并安装node.js
Node.js。
C:\Users\PC
>node -v
v12.18.3
2,安装淘宝镜像
C:\Users\PC
>npm
install -g cnpm --registry
=HTTPS://registry.npm.taobao.org
npm WARN deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142
npm WARN deprecated har-validator@5.1.5: this
C:\Users\PC\AppData\Roaming\npm\cnpm -
> C:\Users\PC\AppData\Roaming\npm\node_modules\cnpm\bin\cnpm
+ cnpm@6.1.1
added 685 packages from 970 contributors
in 28.127s
3,安装vue.js脚手架
C:\Users\PC
>cnpm
install --global vue-cli
Downloading vue-cli to C:\Users\PC\AppData\Roaming\npm\node_modules\vue-cli_tmp
Copying C:\Users\PC\AppData\Roaming\npm\node_modules\vue-cli_tmp\_vue-cli@2.9.6@vue-cli to C:\Users\PC\AppData\Roaming\npm\node_modules\vue-cli
Installing vue-cli's dependencies to C:\Users\PC\AppData\Roaming\npm\node_modules\vue-cli/node_modules
[1/20
] commander@^2.9.0 installed at node_modules\_commander@2.20.3@commander
[2/20
] async@^2.4.0 installed at node_modules\_async@2.6.3@async
[3/20
] consolidate@^0.14.0 installed at node_modules\_consolidate@0.14.5@consolidate
[4/20
] minimatch@^3.0.0 installed at node_modules\_minimatch@3.0.4@minimatch
[5/20
] rimraf@^2.5.0 existed at node_modules\_rimraf@2.7.1@rimraf
[6/20
] multimatch@^2.1.0 installed at node_modules\_multimatch@2.1.0@multimatch
[7/20
] ora@^1.3.0 installed at node_modules\_ora@1.4.0@ora
[8/20
] handlebars@^4.0.5 installed at node_modules\_handlebars@4.7.6@handlebars
[9/20
] semver@^5.1.0 installed at node_modules\_semver@5.7.1@semver
[10/20
] chalk@^2.1.0 installed at node_modules\_chalk@2.4.2@chalk
[11/20
] coffee-script@1.12.7 existed at node_modules\_coffee-script@1.12.7@coffee-script
[12/20
] read-metadata@^1.0.0 installed at node_modules\_read-metadata@1.0.0@read-metadata
[13/20
] uid@0.0.2 installed at node_modules\_uid@0.0.2@uid
[14/20
] user-home@^2.0.0 installed at node_modules\_user-home@2.0.0@user-home
[15/20
] tildify@^1.2.0 installed at node_modules\_tildify@1.2.0@tildify
[16/20
] metalsmith@^2.1.0 installed at node_modules\_metalsmith@2.3.0@metalsmith
[17/20
] validate-npm-package-name@^3.0.0 installed at node_modules\_validate-npm-package-name@3.0.0@validate-npm-package-name
[18/20
] download-git-repo@^1.0.1 installed at node_modules\_download-git-repo@1.1.0@download-git-repo
[19/20
] request@^2.67.0 installed at node_modules\_request@2.88.2@request
[20/20
] inquirer@^6.0.0 installed at node_modules\_inquirer@6.5.2@inquirer
deprecate metalsmith@2.3.0 › gray-matter@2.1.1 › coffee-script@^1.12.4 CoffeeScript on NPM has moved to
"coffeescript" (no hyphen
)
deprecate request@^2.67.0 request has been deprecated, see https://github.com/request/request/issues/3142
deprecate request@2.88.2 › har-validator@~5.1.3 this library is no longer supported
Recently updated
(since 2020-08-28
): 3 packages
(detail see
file C:\Users\PC\AppData\Roaming\npm\node_modules\vue-cli\node_modules\.recently_updates.txt
)
2020-09-03
→ download-git-repo@1.1.0 › download@5.0.3 › decompress@4.2.1 › decompress-tar@4.1.1 › tar-stream@1.6.2 › bl@^1.0.0
(1.2.3
) (17:52:16
)
2020-08-31
→ handlebars@4.7.6 › uglify-js@^3.1.4
(3.10.3
) (00:58:49
)
→ request@2.88.2 › har-validator@5.1.5 › ajv@6.12.4 › uri-js@^4.2.2
(4.4.0
) (03:04:37
)
All packages installed
(233 packages installed from
npm registry, used 7s
(network 6s
), speed 797.88kB/s, json 220
(472.43kB
), tarball 4.54MB
)
[vue-cli@2.9.6
] link C:\Users\PC\AppData\Roaming\npm\vue@ -
> C:\Users\PC\AppData\Roaming\npm\node_modules\vue-cli\bin\vue
[vue-cli@2.9.6
] link C:\Users\PC\AppData\Roaming\npm\vue-init@ -
> C:\Users\PC\AppData\Roaming\npm\node_modules\vue-cli\bin\vue-init
[vue-cli@2.9.6
] link C:\Users\PC\AppData\Roaming\npm\vue-list@ -
> C:\Users\PC\AppData\Roaming\npm\node_modules\vue-cli\bin\vue-list
4,创建并运行vue项目
F:\PythonProjects\web\goods
>vue init webpack-simple demo1
? Project name demo1
? Project description A Vue.js project
? Author
? License MIT
? Use sass? No
F:\PythonProjects\web\goods
>cnpm
install
√ All packages installed
(723 packages installed from
npm registry, used 26s
(network 26s
), speed 628.15kB/s, json 635
(1.61MB
), tarball 14.18MB
)
F:\PythonProjects\web\python django web dianxing\goods\demo1
>npm run dev
> demo1@1.0.0 dev F:\PythonProjects\web\goods\demo1
> cross-env NODE_ENV
=development webpack-dev-server --open --hot
Project is running at http://localhost:8080/
webpack output is served from /dist/
404s will fallback to /index.html
{ parser:
"babylon" } is deprecated
; we now treat it as
{ parser:
"babel" }.
5,前端内容
在src/App.vue中添加: 1,HTML:
<template
>
<div id
="app">
<div class
="all">
<div class
="one">
<div class
="onetype" v-for
="(item,index) in one" :key
="index">
<b
>{{one
[index
]}}</b
>
</div
>
</div
>
<div class
="twothreefour">
<div class
="two">
<div class
="twotype"
v-for
="(item,index) in two" :key
="index"
@mouseenter
="open(index)">
<b
>{{two
[index
]}}</b
>
</div
>
</div
>
<div class
="threefour" v-if
="flag"
@mouseleave
="close()">
<div class
="threefourtype" v-for
="(item,index) in three" :key
="index">
<span class
="three">{{three
[index
]}}</span
>
<span class
="four" v-for
="(item4,index4) in four" :key
="index4">{{four
[index4
]}}</span
>
</div
>
</div
>
</div
>
</div
>
</div
>
</template
>
2,JavaScript:
<script
>
export default
{
name:
'app',
data
() {
return {
one:
['一级类目',
'一级类目',
'一级类目',
'一级类目',
'一级类目'],
two:
['二级类目1',
'二级类目2',
'二级类目3',
'二级类目4',
'二级类目5'],
three:
[],
four:
['四级类目',
'四级类目',
'四级类目',
'四级类目',
'四级类目'],
flag:false
}
},
methods:
{
open
(index
){
var index
=index+1
;
var i
=index+
"";
this.three
=['三级目录'+i,
'三级目录'+i,
'三级目录'+i,
'三级目录'+i,
'三级目录'+i
]
this.flag
=true
},
close
(){
this.flag
=false
}
},
}
</script
>
3,css:
<style
>
*
{
/* 样式初始化 */
box-sizing: border-box
;
margin: 0
;
padding: 0
;
}
.all
{
/* 将整个导航栏组件做整体设置 */
/*宽度占浏览器80%,高度400px;背景灰色;上外边距50px
; 左右居中*/
/* 设置为flex弹性盒子,并且定义为高度不够自动折行模式,用于横向排列子元素 */
width: 80%
;
height: 400px
;
background:
margin: 50px auto
;
display: -webkit-flex
; /* Safari */
display: flex
;
flex-wrap: wrap
;
}
.one
{
/* 设置一级类目所占地区的样式,宽度占满all盒子的100% */
width: 100%
;
height: 50px
;
background:
display: flex
;
display: -webkit-flex
; /* Safari */
flex-wrap: wrap
;
/* 弹性盒子内部的子元素都均匀排列成一横排,并且左右两边都留有一定空隙 */
justify-content: space-around
;
}
.onetype
{
width: 20%
;
height: 50px
;
line-height: 50px
;
text-align: center
;
}
.onetype:hover
{
background-color:chocolate
;
color:
}
.twothreefour
{
/* 盛放二三四级目录的盒子 */
width: 100%
;
height: 350px
;
background:
display: -webkit-flex
; /* Safari */
display: flex
;
flex-wrap: wrap
;
/* 弹性盒子内部的子元素都均匀排列成一横排,并且左右两边都不留空隙 */
justify-content: space-between
;
}
.two
{
/* 设置盛放二级类目的弹性盒子 */
width: 15%
;
height: 100%
;
background:
display: -webkit-flex
; /* Safari */
display: flex
;
/* 弹性盒子内部的子元素从上到下排成一列 */
flex-direction: column
;
}
.twotype
{
width: 100%
;
height: 40px
;
line-height: 40px
;
text-align: center
;
background:
}
.twotype:hover
{
background-color:black
;
color:
}
.threefour
{
width: 40%
;
margin-right: 45%
;
height: 100%
;
background:
display: -webkit-flex
; /* Safari */
display: flex
;
flex-direction: column
;
}
.threefourtype
{
margin: 10px auto
;
}
.three
{
font-family: 微软雅黑, 黑体
;
font-size: 16px
;
font-weight: 800
;
}
.four
{
font-family: 宋体
;
font-size: 12px
;
font-weight: 400
;
}
</style
>
二,前后端分离
前端vue.js将请求通过API发送给后端,后端进行请求处理并作出请求响应,前端获取相应数据后赋值给data从而更改前端页面内容。
三,后端项目
1,创建开发环境及项目
项目目录结构如下: 安装DRF等依赖包:
pip
install Djangorestframework markdown Django-filter pillow Django-guardian coreapi
2,创建商品类别模型并添加数据
from django.db
import models
from datetime
import datetime
class Type1
(models.Model
):
"""
一级类目
"""
name
= models.CharField
(max_length
=10, default
="", verbose_name
="类目名")
add_time
= models.DateTimeField
(default
=datetime.now, verbose_name
='添加时间')
class Meta:
verbose_name
= '商品类别'
verbose_name_plural
= verbose_name
def __str__
(self
):
return self.name
class Type2
(models.Model
):
"""
二级类目
"""
parent
= models.ForeignKey
(Type1, verbose_name
="父级类别",
null
=True, blank
=True, on_delete
=models.CASCADE
)
name
= models.CharField
(max_length
=10, default
="", verbose_name
="类目名")
add_time
= models.DateTimeField
(default
=datetime.now, verbose_name
='添加时间')
class Meta:
verbose_name
= '商品类别2'
verbose_name_plural
= verbose_name
def __str__
(self
):
return self.name
class Type3
(models.Model
):
"""
三级类目
"""
parent
= models.ForeignKey
(Type2, verbose_name
="父级类别",
null
=True, blank
=True, on_delete
=models.CASCADE
)
name
= models.CharField
(max_length
=10, default
="", verbose_name
="类目名")
add_time
= models.DateTimeField
(default
=datetime.now, verbose_name
='添加时间')
class Meta:
verbose_name
= '商品类别3'
verbose_name_plural
= verbose_name
def __str__
(self
):
return self.name
class Type4
(models.Model
):
"""
四级类目
"""
parent
= models.ForeignKey
(Type3, verbose_name
="父级类别",
null
=True, blank
=True, on_delete
=models.CASCADE
)
name
= models.CharField
(max_length
=10, default
="", verbose_name
="类目名")
add_time
= models.DateTimeField
(default
=datetime.now, verbose_name
='添加时间')
class Meta:
verbose_name
= '商品类别4'
verbose_name_plural
= verbose_name
def __str__
(self
):
return self.name
数据迁移并添加一些数据到表中。
3,实现序列化
app01/serializers.py:
from rest_framework
import serializers
from .models
import Type1, Type2, Type3, Type4
class Type1ModelSerializer
(serializers.ModelSerializer
):
class Meta:
model
= Type1
fields
= "__all__"
class Type2ModelSerializer
(serializers.ModelSerializer
):
class Meta:
model
= Type2
fields
= "__all__"
class Type3ModelSerializer
(serializers.ModelSerializer
):
class Meta:
model
= Type3
fields
= "__all__"
class Type4ModelSerializer
(serializers.ModelSerializer
):
class Meta:
model
= Type4
fields
= "__all__"
app01/views.py:
from app01.serializers
import Type1ModelSerializer, Type2ModelSerializer
from app01.serializers
import Type3ModelSerializer, Type4ModelSerializer
from app01.models
import Type1, Type2, Type3, Type4
from rest_framework.views
import APIView
from rest_framework.response
import Response
from rest_framework.renderers
import JSONRenderer, BrowsableAPIRenderer
class Type1View
(APIView
):
"""
all Type1
"""
renderer_classes
= [JSONRenderer
]
def get
(self, request, format
=None
):
types
= Type1.objects.all
()
types_serializer
= Type1ModelSerializer
(types, many
=True
)
return Response
(types_serializer.data
)
class Type2View
(APIView
):
"""
all Type2
"""
renderer_classes
= [JSONRenderer
]
def get
(self, request, format
=None
):
types
= Type2.objects.all
()
types_serializer
= Type2ModelSerializer
(types, many
=True
)
return Response
(types_serializer.data
)
class Type3View
(APIView
):
"""
all Type3
"""
renderer_classes
= [JSONRenderer
]
def get
(self, request, format
=None
):
types
= Type3.objects.all
()
types_serializer
= Type3ModelSerializer
(types, many
=True
)
return Response
(types_serializer.data
)
class Type4View
(APIView
):
"""
all Type4
"""
renderer_classes
= [JSONRenderer
]
def get
(self, request, format
=None
):
types
= Type4.objects.all
()
types_serializer
= Type4ModelSerializer
(types, many
=True
)
return Response
(types_serializer.data
)
4,路由
app01/urls.py:
from django.urls
import path
from app01.views
import *
urlpatterns
= [
path
('type1/', Type1View.as_view
(), name
='type1'),
path
('type2/', Type2View.as_view
(), name
='type2'),
path
('type3/', Type3View.as_view
(), name
='type3'),
path
('type4/', Type4View.as_view
(), name
='type4'),
]
demo2/urls.py:
from django.contrib
import admin
from django.urls
import path, include
urlpatterns
= [
path
('admin/', admin.site.urls
),
path
('api/', include
("app01.urls"), name
='api')
]
四,前后端联合调试
1,给前端添加网络请求模块
F:\PythonProjects\web\python django web dianxing\goods\demo1
>cnpm
install axios --save
√ Installed 1 packages
√ Linked 1 latest versions
√ Run 0 scripts
√ All packages installed
(1 packages installed from
npm registry, used 2s
(network 2s
), speed 48.13kB/s, json 2
(9.1kB
), tarball 92.65kB
)
2,改写前端内容
<template
>
<div id
="app">
<div class
="all">
<div class
="one">
<div class
="onetype" v-for
="(item,index) in one" :key
="index">
<b
>{{one
[index
].name
}}</b
>
</div
>
</div
>
<div class
="twothreefour">
<div class
="two">
<div class
="twotype"
v-for
="(item,index) in two" :key
="index"
@mouseenter
="open(index)">
<b
>{{two
[index
].name
}}</b
>
</div
>
</div
>
<div class
="threefour" v-if
="flag"
@mouseleave
="close()">
<div class
="threefourtype" v-for
="(item,index) in three1" :key
="index">
<span class
="three">{{three1
[index
]}}</span
>
<span class
="four" v-for
="(item4,index4) in four1" :key
="index4">
{{four1
[index4
]}} 
;</span
>
</div
>
</div
>
</div
>
</div
>
</div
>
</template
>
<script
>
import Axios from
'axios';
export default
{
name:
'app',
data
() {
return {
one:
[],
two:
[],
three:
[],
four:
[],
flag:false,
three1:
[],
four1:
[]
}
},
methods:
{
getData
(){
const api
='http://127.0.0.1:8000/';
var api1
=api+
'api/type1/';
var api2
=api+
'api/type2/';
var api3
=api+
'api/type3/';
var api4
=api+
'api/type4/';
var type1
=[];
var type2
=[];
var type3
=[];
var type4
=[];
Axios.get
(api1
)
.then
(function
(response
) {
// console.log
(response
);
for
(var i
=0
;i
<response.data.length
;i++
){
// console.log
(response.data
[i
])
type1.push
(response.data
[i
])
}
// console.log
(type1
)
})
.catch
(function
(error
) {
console.log
(error
);
});
this.one
=type1
;
Axios.get
(api2
)
.then
(function
(response
) {
// console.log
(response
);
for
(var i
=0
;i
<response.data.length
;i++
){
// console.log
(response.data
[i
])
type2.push
(response.data
[i
])
}
// console.log
(type2
)
})
.catch
(function
(error
) {
console.log
(error
);
});
this.two
=type2
;
Axios.get
(api3
)
.then
(function
(response
) {
// console.log
(response
);
for
(var i
=0
;i
<response.data.length
;i++
){
// console.log
(response.data
[i
])
type3.push
(response.data
[i
])
}
// console.log
(type3
)
})
.catch
(function
(error
) {
console.log
(error
);
});
this.three
=type3
;
Axios.get
(api4
)
.then
(function
(response
) {
// console.log
(response
);
for
(var i
=0
;i
<response.data.length
;i++
){
// console.log
(response.data
[i
])
type4.push
(response.data
[i
])
}
// console.log
(type4
)
})
.catch
(function
(error
) {
console.log
(error
);
});
this.four
=type4
;
// console.log
(this.one
)
// console.log
(this.two
)
// console.log
(this.three
)
// console.log
(this.four
)
},
open
(index
){
// console.log
(this.two
[index
].id
)
var temp
=[]
for
(var i
=0
;i
<this.three.length
;i++
){
if
(this.three
[i
].parent
===index+1
){
temp.push
(this.three
[i
].name
)
}
}
console.log
(temp
)
this.three1
=temp
;
var temp4
=[]
for
(var j
=0
;j
<this.four.length
;j++
){
temp4.push
(this.four
[j
].name
)
}
this.four1
=temp4
this.flag
=true
},
close
(){
this.flag
=false
}
},
mounted
() {
this.getData
()
},
}
</script
>
css保留
3,后端设置跨域访问
略。
4,分别启动前后端
四级菜单并未进行分类,可仿照三级菜单改进。