感谢 Django-vue-admin 开源项目组的支持
开发是最重要的还是实战,如何能够快速理解掌握,当然是使用开源平台来进行研究学习。当然开源项目非常多,如何寻找变成了难事。这里我建议,如果是新手,先去Gitee进行开源搜找(毕竟这是国内开源第一地方)也有很多人可以交流,倘若一开始就去Github找开源项目,先不说语言问题,就单单能不能自己跑出来都是问题,一个Web项目如果在本地运行起来需要一定的基础功底。一个项目最重要的是先跑出来然后才有心思去研究。
此开源项目采用前后端分离,采用的接口设计,本来我之前是想找若依框架进行学习的,发现没有python-django版本的,全都是java版本,所以也索性选择了这个还不错的快速开发平台。
前端技术:D2Admin Vue ElementUI
后端技术:Django ,Django rest framework
权限认证:Django REST FRAMEWORK SIMPLEJWT
web开源项目可以进行二次开发,简单来说可以根据现有的东西来自取所需,留下需要的,并进行开发与部署(开源准则),所以以此框架进行课设亦或者毕业设计也是相当绰绰有余。本项目学习的点非常多,下面我也会抽时间对常见的技术模块进行讲解。
开源项目地址:
Gitee链接
Github链接
项目首页部分
目录
环境配置
本次环境使用的IDE为Pycharm 2022.
对于开发环境是Python 3.7.9 Mysql 5.7 nodejs 18.2
前面两个没什么问题,主要是nodejs(基于服务端)。
Node.js 是一个开源和跨平台的Javascript运行环境。其中npm以简单的结构帮助Node.js蓬勃发展。
下载nodejs,并默认环境变量配置。
进入到nodejs目录下,创建node_cache和node_global
最好使用cmd管理员命令
# 检测是否安装node.jsnode -v
#设置npm安装程序时的默认位置npm config set prefix "C:\Tools\Nodejs\node_global"#设置npm安装程序时的缓存位置npm config set cache "C:\Tools\Nodejs\node_cache"#并把环境变量添加到PATH中
NODE_PATH:C:\Tools\Nodejs
PATH:C:\Tools\Nodejs\node_global
同时使用pycharm打开项目,在项目-python解释器选择(添加)
建造虚拟环境,这样此时的终端就是和项目一样的python版本与pip包了。
克隆项目
git clone https://gitee.com/liqianglog/django-vue-admin.git
前端搭建
注意,为保证npm启动服务正常,这里统一使用cmd(管理员运行)。
# 进行web目录,首先输入 D: 进入D盘cd web
下面是安装依赖,在这一方面我尝试了非常久的办法,遇到了不少麻烦,下面我将以上面的nodejs环境为例进行搭建:
# 首先清除缓存npm cache clean --force
# 设置淘宝源npm config set registry https://registry.npm.taobao.org
# 运行安装npminstall# 安装依赖npminstall --registry=https://registry.npm.taobao.org
在此过程中可能由于版本问题会报错,Error: error:0308010C:digital envelope routines::unsupported。
那么首先先降低npm版本:
npminstall [email protected] -g
重新配置淘宝下载镜像:
npm config set registry "https://registry.npm.taobao.org"# 再安装一下依赖npminstall --registry=https://registry.npm.taobao.org
# 安装yarnnpminstall --global yarn
当然由于node版本过高,必须要进行安全配置才可以启动前端项目:
cmd输入,每次运行前都需要输入
setNODE_OPTIONS=--openssl-legacy-provider
接着就可以运行了
npm run dev
# 浏览器访问 http://localhost:8080# .env.development 文件中可配置启动端口等参数# 构建生产环境# npm run build
看到这样,恭喜前端跑起来了!
此时会自动跳转到默认浏览器中,不过由于没有设置后端操作,所以也无法登录。
后端操作
后端基本就是Python django的常规操作了。
首先是准备数据库
# 建一个 dv 数据库,这里就是字符集与排序顺序
CREATE DATABASE IF NOT EXISTS dv DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_general_ci;#在mysql中请大家忘记**utf8**,永远使用**utf8mb4**
1. 进入项目目录 cd backend
2. 在项目根目录中,复制 ./conf/env.example.py 文件为一份新的到 ./conf 文件夹下,并重命名为 env.py
3. 在 env.py 中配置数据库信息
mysql数据库版本建议:8.0
mysql数据库字符集:utf8mb4
4. 安装依赖环境
pip install -r requirements.txt
5. 执行迁移命令:
python manage.py makemigrations
python manage.py migrate
6. 初始化数据
python manage.py init
7. 初始化省市县数据:
python manage.py init_area
8. 启动项目
python manage.py runserver 0.0.0.0:8000
或使用 daphne :
daphne -b 0.0.0.0 -p 8000 application.asgi:application
登录以后就来到了如下界面:
快速构建数据操作页面
这里以上述项目为框架进行搭建一个简易的图书管理页面,具体方法如下:
其中在pycharm中需要指定源文件目录(项目根目录),这样才不会解析未引用:
#进入后端目录cd backend
#新建一个后端应用名称为book
python manage.py startapp book
进行数据库表的构造:
from django.db import models
from dvadmin.utils.models import CoreModel, table_prefix
classBook(CoreModel):
book_no = models.CharField(max_length=24,unique=True, verbose_name='书籍编号', help_text="书籍编号")
book_name = models.CharField(max_length=24,null=False, verbose_name='书籍名称', help_text="书籍名称")classMeta:
db_table = table_prefix +"book"
verbose_name ='书籍表'
verbose_name_plural = verbose_name
ordering =('-create_datetime',)
# book/settings.py
INSTALLED_APPS:'book'
进行表的迁移:
python manage.py makemigrations book
python manage.py migrate book
创建过滤器,序列化器,视图:
# book/views.py# Create your views here.from book.models import Book
from dvadmin.utils.serializers import CustomModelSerializer
from dvadmin.utils.viewset import CustomModelViewSet
classBookSerializer(CustomModelSerializer):"""
书籍-序列化器
"""classMeta:
model = Book
fields ="__all__"
read_only_fields =["id"]classBookCreateUpdateSerializer(CustomModelSerializer):"""
书籍管理 创建/更新时的列化器
"""classMeta:
model = Book
fields ='__all__'# 以上是序列化函数,可以使用新建一个serializers.py来进行管理classBookViewSet(CustomModelViewSet):"""
书籍管理接口
list:查询
create:新增
update:修改
retrieve:单例
destroy:删除
"""
queryset = Book.objects.all()
serializer_class = BookSerializer
extra_filter_backends =[]
permission_classes =[]
search_fields =['label']
添加路由:
# book/urls.pyfrom rest_framework import routers
from book.views import BookViewSet
book_url = routers.SimpleRouter()
book_url.register(r'book', BookViewSet)
urlpatterns =[]
urlpatterns += book_url.urls
backend/application/urls.py
path('api/', include('book.urls')),
以上后端的操作就全部完成了:
先运行后端,运行成功后将会进入到接口部分,表面后端操作已经实现
下面进行前端展示:
在src/view下新建一个目录,新建api.js curd.js index.vue
# api.js
import{ request }from'@/api/service'exportconst urlPrefix ='/api/book/'/**
* 列表查询
*/exportfunctionGetList(query){
query.limit =999returnrequest({url: urlPrefix,method:'get',params: query
})}/**
* 新增
*/exportfunctioncreateObj(obj){returnrequest({url: urlPrefix,method:'post',data: obj
})}/**
* 修改
*/exportfunctionUpdateObj(obj){returnrequest({url: urlPrefix + obj.id +'/',method:'put',data: obj
})}/**
* 删除
*/exportfunctionDelObj(id){returnrequest({url: urlPrefix + id +'/',method:'delete',data:{ id }})}
# crud.js
import{ request }from'@/api/service'import{BUTTON_STATUS_NUMBER}from'@/config/button'import{ urlPrefix as bookPrefix }from'./api'exportconstcrudOptions=(vm)=>{return{pageOptions:{compact:true},options:{tableType:'vxe-table',rowKey:true,// 必须设置,true or falserowId:'id',height:'100%',// 表格高度100%, 使用toolbar必须设置highlightCurrentRow:false,},rowHandle:{width:140,view:{thin:true,text:'',disabled(){return!vm.hasPermissions('Retrieve')}},edit:{thin:true,text:'',disabled(){return!vm.hasPermissions('Update')}},remove:{thin:true,text:'',disabled(){return!vm.hasPermissions('Delete')}}},indexRow:{// 或者直接传true,不显示title,不居中title:'序号',align:'center',width:100},viewOptions:{componentType:'form'},formOptions:{defaultSpan:24,// 默认的表单 spanwidth:'35%'},columns:[{title:'关键词',key:'search',show:false,disabled:true,search:{disabled:false},form:{disabled:true,component:{props:{clearable:true},placeholder:'请输入关键词'}},view:{// 查看对话框组件的单独配置disabled:true}},{title:'ID',key:'id',show:false,disabled:true,width:90,form:{disabled:true}},{title:'书籍编码',key:'book_no',sortable:true,treeNode:true,search:{disabled:false,component:{props:{clearable:true}}},type:'input',form:{editDisabled:true,rules:[// 表单校验规则{required:true,message:'编码必填项'}],component:{props:{clearable:true},placeholder:'请输入编码'},itemProps:{class:{yxtInput:true}}}},{title:'书名',key:'book_name',sortable:true,search:{disabled:false,component:{props:{clearable:true}}},type:'input',form:{rules:[// 表单校验规则{required:true,message:'显示值必填项'}],component:{props:{clearable:true},placeholder:'请输入显示值'},itemProps:{class:{yxtInput:true}}}},].concat(vm.commonEndColumns())}}
# index.vue
# 主要改name名
<template><d2-container :class="{ 'page-compact': crud.pageOptions.compact }"><!--<template slot="header">测试页面1</template>--><d2-crud-x ref="d2Crud" v-bind="_crudProps" v-on="_crudListeners"><div slot="header"><crud-search
ref="search":options="crud.searchOptions"
@submit="handleSearch"/><el-button-group><el-button size="small" type="primary" @click="addRow"><i class="el-icon-plus"/> 新增</el-button
></el-button-group><crud-toolbar
:search.sync="crud.searchOptions.show":compact.sync="crud.pageOptions.compact":columns="crud.columns"
@refresh="doRefresh()"
@columns-filter-changed="handleColumnsFilterChanged"/></div></d2-crud-x></d2-container></template><script>import*as api from'./api'import{ crudOptions }from'./crud'import{ d2CrudPlus }from'd2-crud-plus'exportdefault{name:'book',mixins:[d2CrudPlus.crud],data(){return{}},methods:{getCrudOptions(){returncrudOptions(this)},pageRequest(query){return api.GetList(query)},addRequest(row){
d2CrudPlus.util.dict.clear()return api.createObj(row)},updateRequest(row){
d2CrudPlus.util.dict.clear()return api.UpdateObj(row)},delRequest(row){return api.DelObj(row.id)},// 授权createPermission(scope){this.$router.push({name:'menuButton',params:{id: scope.row.id },query:{name: scope.row.name }})}}}</script><style lang="scss">.yxtInput {.el-form-item__label {color: #49a1ff;}}</style>
此框架最方便的步骤来了,不需要自行搭建,这里使用框架中的菜单管理,进行页面展示:
先添加相应的信息:
由于我按确定没用,所以采取了这个办法:
完成以后将会变成这个样子,这就是我们刚刚建立的页面,数据库信息已经读入:
项目部分分析
由于这个项目非常庞大,里面内涵的东西非常多,在这里也不可能一下子讲完,而且部分技术非常新颖。
首先是前端框架技术:
Vue是一个用于创建用户界面的开源MVVM前端JavaScript框架,也是一个创建单页应用的Web应用框架。在这里构建的时候主要是对于Index.vue中的name修改。
整体目录
├──web///前端项目├──backend///后端项目├──docker_env///docker安装配置├──docker-compose.yml//docker-compose配置├──README.md//项目的说明文档├──LICENSE//开源LICENSE└──README.md//说明文档
前端目录
├──README.md//项目的说明文档├──dist//build后存放内容├──package.json//npm包配置文件,里面定义了项目的npm脚本,依赖包等信息├──babel.config.js//babel├──public//项目根目录│├──image///主题展示目录│├──icon.ico//ico图标│└──index.html//首页入口文件,你可以添加一些meta信息或统计代码啥的。├──src//开发的目录│├──App.vue//项目入口文件│├──api//系统公告api接口│├──assets//项目公用资源目录(图片,ico)│├──components//公共组件│├──config//基本配置│├──layout//全局layout│├──libs//全局公用方法│├──locales//国际化│├──menu//菜单权限处理│├──plugin//d2admin前端插件│├──router//路由│├──store//全局store管理│└──views//views所有页面│├──dashboard//首页内容│├──demo//demo示例│├──plugins//dvadmin插件│├──system//dvadmin系统专有视图,建议不要修改或新增内容││├──...││├──login//登录页面││└──...│├──App.vue//vueApp入口│├──install.js//d2admin前端通用配置│├──main.js//vuemain入口│└──setting.js//d2admin配置│├──main.js//项目的核心文件│├──permission.js//页面是否登录判断权限判断,权限白名单│├──settings.js//全局配置│├──.env.development//开发环境配置│├──.env.staging//预发布环境配置│├──.env.production//生产环境配置│└──...└──vue.config.js//本地跨域代理
后端目录
├──application//工程名称│├──asgi.py//Djangoasgi默认配置│├──celery.py//celery默认配置│├──settings.py//项目的settings配置│├──urls.py//项目主URL对应关系│└──wsgi.py//wsgi默认配置├──conf//配置信息│├──env.example.py//配置信息模板│└──env.py//自行根据env.example.py复制重命名为env.py,系统只会去读取env.py配置├──dvadmin//docker启动celery脚本│├──system//dvadmin系统app│└──utils//全局公用方法├──logs//日志存放位置├──media//上传的文件存放位置├──plugins//dvadmin插件目录├──└──...│──static//静态文件│├──drf-yasg//静态文件drf-yasg静态文件│├──...│└──rest_framework//rest_framework静态文件├──docker_start.sh//docker启动django脚本├──manage.py└──requirements.txt//项目环境依赖
在本项目中使用的接口操作,比如在刚刚book等增删改查部分:
classBookViewSet(CustomModelViewSet):"""
书籍管理接口
list:查询
create:新增
update:修改
retrieve:单例
destroy:删除
"""
queryset = Book.objects.all()
serializer_class = BookSerializer
extra_filter_backends =[]
permission_classes =[]
search_fields =['label']
就这么多语句完成了增删改查部分。
主要的技术:统一标准的返回格式;新增,查询,修改可使用不同序列化器(1)ORM性能优化, 尽可能使用values_queryset形式(2)create_serializer_class 新增时,使用的序列化器(3)update_serializer_class 修改时,使用的序列化器。这是十分便捷的技术,需要在日后强化。
版权归原作者 三金C_C 所有, 如有侵权,请联系我们删除。