一个简单的前后端分离demo

tech2025-06-24  5

功能类似于:

一,安装及简单配置前端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:#eee; margin: 50px auto; display: -webkit-flex; /* Safari */ display: flex; flex-wrap: wrap; } .one{ /* 设置一级类目所占地区的样式,宽度占满all盒子的100% */ width: 100%; height: 50px; background: #FF8888; 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: #eee; } .twothreefour{ /* 盛放二三四级目录的盒子 */ width: 100%; height: 350px; background: #66FF66; display: -webkit-flex; /* Safari */ display: flex; flex-wrap: wrap; /* 弹性盒子内部的子元素都均匀排列成一横排,并且左右两边都不留空隙 */ justify-content: space-between; } .two{ /* 设置盛放二级类目的弹性盒子 */ width: 15%; height: 100%; background: #77FFCC; display: -webkit-flex; /* Safari */ display: flex; /* 弹性盒子内部的子元素从上到下排成一列 */ flex-direction: column; } .twotype{ width: 100%; height: 40px; line-height: 40px; text-align: center; background: #EEFFBB; } .twotype:hover{ background-color:black; color: #eee; } .threefour{ width: 40%; margin-right: 45%; height: 100%; background: #33FFDD; 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 # Create your models here. 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 # Create your views here. 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]}}&nbsp;</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,分别启动前后端

四级菜单并未进行分类,可仿照三级菜单改进。
最新回复(0)