项目初始化
前端
开发
# 克隆项目
git clone https://gitee.com/dvadmin/django-vue-admin-pro.git
# 进入项目目录
cd web
# 安装依赖
npm install --registry=https://registry.npm.taobao.org
# 启动服务
npm run dev
# 浏览器访问 http://localhost:8080
# .env.development 文件中可配置启动端口等参数
发布
# 构建测试环境
npm run build:stage
# 构建生产环境
npm run build:prod
准备数据库
#建库 mysql库名如 dv 语句如下
CREATE DATABASE IF NOT EXISTS dv DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_general_ci;
后端
1. 进入项目目录 cd backend
2. 在项目根目录中,复制 ./conf/env.example.py 文件为一份新的到 ./conf 文件夹下,并重命名为 env.py
3. 在 env.py 中配置数据库信息(上面刚建立的库)
4. 安装依赖环境
pip3 install -r requirements.txt
5. 执行迁移命令:
python3 manage.py makemigrations
python3 manage.py migrate
6. 初始化数据
python3 manage.py init
7. 启动项目
python3 manage.py runserver 127.0.0.1:8000
或使用 daphne :
daphne -b 0.0.0.0 -8000 application.asgi:application
初始账号:superadmin 密码:admin123456
后端接口文档地址:http://127.0.0.1:8000/swagger
新建一个页面
举例新建一个图书管理的增删改查页面
后端
-
Django创建app
#进入后端目录 cd backend #新建一个后端应用名称为book python3 manage.py startapp book
-
建表,修改models.py文件,位于 backend/book下,内容如下
from django.db import models from dvadmin.utils.models import CoreModel, table_prefix class Book(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="书籍名称") class Meta: db_table = table_prefix + "book" verbose_name = '书籍表' verbose_name_plural = verbose_name ordering = ('-create_datetime',)
-
Setting 注册一下app 路径backend/application/settings.py book加到最后 参考如下
INSTALLED_APPS = [ 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'django_comment_migrate', 'rest_framework', 'django_filters', 'corsheaders', # 注册跨域app 'dvadmin.system', 'drf_yasg', 'captcha', 'book', ]
-
迁移数据库,创建book表,book表会继承CoreModel里面定义的基础核心字段
python3 manage.py makemigrations book python3 manage.py migrate book
-
创建过滤器、序列化器、视图 全部写在views.py里面
# Create your views here. from book.models import Book from dvadmin.utils.serializers import CustomModelSerializer from dvadmin.utils.viewset import CustomModelViewSet class BookSerializer(CustomModelSerializer): """ 书籍-序列化器 """ class Meta: model = Book fields = "__all__" read_only_fields = ["id"] class BookCreateUpdateSerializer(CustomModelSerializer): """ 书籍管理 创建/更新时的列化器 """ class Meta: model = Book fields = '__all__' class BookViewSet(CustomModelViewSet): """ 书籍管理接口 list:查询 create:新增 update:修改 retrieve:单例 destroy:删除 """ queryset = Book.objects.all() serializer_class = BookSerializer extra_filter_backends = [] permission_classes = [] search_fields = ['label']
-
添加路由
在book目录下添加urls.py文件,内容如下
from 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目录下添加上面的路由 urlpatterns 加入下面的内容
path('api/', include('book.urls')),
-
测试接口
#访问swagger 测试后端接口 登录账号上面写了 确认有book的接口了 后端完成 http://127.0.0.1:8000
- ...
前端
在 src/view 下新建目录book 然后新建三个文件 api.js curd.js index.vue
-
api.js
import { request } from '@/api/service' export const urlPrefix = '/api/book/' /** * 列表查询 */ export function GetList (query) { query.limit = 999 return request({ url: urlPrefix, method: 'get', params: query }) } /** * 新增 */ export function createObj (obj) { return request({ url: urlPrefix, method: 'post', data: obj }) } /** * 修改 */ export function UpdateObj (obj) { return request({ url: urlPrefix + obj.id + '/', method: 'put', data: obj }) } /** * 删除 */ export function DelObj (id) { return request({ url: urlPrefix + id + '/', method: 'delete', data: { id } }) }
-
curd.js
import { request } from '@/api/service' import { BUTTON_STATUS_NUMBER } from '@/config/button' import { urlPrefix as bookPrefix } from './api' export const crudOptions = (vm) => { return { pageOptions: { compact: true }, options: { tableType: 'vxe-table', rowKey: true, // 必须设置,true or false rowId: 'id', height: '100%', // 表格高度100%, 使用toolbar必须设置 highlightCurrentRow: false, }, rowHandle: { 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', 100 }, viewOptions: { componentType: 'form' }, formOptions: { defaultSpan: 24, // 默认的表单 span '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, 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: 'book', 修改成实际的名字
<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' export default { name: 'book', mixins: [d2CrudPlus.crud], data () { return {} }, methods: { getCrudOptions () { return crudOptions(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>
菜单管理
新增页面
新增页面权限
新增
编辑
删除
查询
最后展示页面完成效果