一步步完整搭建一个图纸管理系统(Django+Vue3)——3、前后端交互

前言: 网上Django项目要么太老,要么不全。正好手里有个需求,借这个机会用django3.2加vue3(TS)一步步完整搭建一个图纸管理系统。一方面是记录,另一方面也回馈开源精神。希望和大家一起学习一起进步。本篇为前后端交互(最近更新7.26)

经过我们前期的努力,已经完成了后端前端的编写。那么接下来就是进行积木搭建的最后一步了!前后端交互!

三、前后端交互

1、前端跨域获取后端接口数据

这里简单说下这个流程大概是什么样子的:

a:前端如何发送获取数据的请求

axios–>Ajax

前端访问地址:http://localhost:8080/

b:后端接受请求,去数据库查询数据,返回json数据给前端

DRF –> 接口

前端访问地址:http://localhost:8000

c:前端把数据展示在页面中去

那什么是跨域呢?

前端当前的地址和后端访问的地址有三个中有一个不一样,就叫跨域

a.协议:http[都一样]

b.IP地址192.168.0.1 192.168.0.2 [不一样]

c.端口8080 8000 [不一样]

1.1 跨域获取所有图纸信息

先安装axios包:npm install axios@0.26.1

image.png

如何直接运行,会发现拿不到数据,因为我们没有对跨域进行处理

image.png

先在setting.py中加入

ALLOWED_HOSTS = ['*',]

然后在manage.py中加入

import os
import sys
​





​
def main():
    """Run administrative tasks."""
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'TestPlatform.settings')
    try:
        from django.core.management import execute_from_command_line
    except ImportError as exc:
        raise ImportError(
            "Couldn't import Django. Are you sure it's installed and "
            "available on your PYTHONPATH environment variable? Did you "
            "forget to activate a virtual environment?"
        ) from exc
    execute_from_command_line(sys.argv)
​
​

if __name__ == "__main__":
    from django.core.management.commands.runserver import Command as Runserver
    Runserver.default_addr = 'localhost' # 修改默认地址  
    Runserver.default_port = '8000' # 修改默认端口  
    main()

这样可以保证后端运行都在localhost:8000

我们需要安装一个插件完成跨域

pip install django-cors-headers==3.11.0

安装好后配置:

image.png

最后在settings.py中加入

# ============跨域请求=============
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_WHITELIST = (
    'http://localhost:8080',
)

运行后会发现可以拿到后端数据了

image.png

进行代码优化,把获取的数据放到前端页面上

image.png

效果为:

image.png

为了友好型,如果加载车成功给一个提示语句

导入

// 导入ElementPlus
import { ElMessage,ElMessageBox } from 'element-plus'

image.png

1.2 优化信息展示

对现实数据条数优化

image.png

我们发现拿到的数据现实属于什么传感器,属于什么项目都是id不是我们要的文字,对此我们需要这样处理:

'''
@Project :gveInformationSystemBE 
@File    :serializer.py
@IDE     :PyCharm 
@Author  :HXW
@Date    :2023/5/23 15:48 
'''
# ===========
from rest_framework import serializers
from DrawingManagementSystem.models import Sensor, Project, Data, Drawing
​

​
# ----Sensor序列化类----
class SensorSerialzer(serializers.ModelSerializer):
    class Meta:
        model = Sensor
        fields = "__all__"
​

# ____Project序列化类____
class ProjectSerialzer(serializers.ModelSerializer):
    sensor = SensorSerialzer()
    class Meta:
        model = Project
        fields = "__all__"
​




# ____Data序列化类____
class DataSerialzer(serializers.ModelSerializer):
    project = ProjectSerialzer()
    class Meta:
        model = Data
        fields = "__all__"
​
# ____Drawing序列化类____
class DrawingSerialzer(serializers.ModelSerializer):
    data = DataSerialzer()
    class Meta:
        model = Drawing
        fields = "__all__"

效果为:

image.png

表格过长呢?

只需要在后面加:show-overflow-tooltip=”true”

 <!-- 2.表格部分 -->

      <el-table :data="Data.drawing" border style="width: 100%" :header-cell-style="{ backgroundColor:'#409EFF',color:'#FFF',fontSize:'14px' }">

      <el-table-column label="序号" type="index" align="center" width="60" />

      <el-table-column prop="material_code" label="物料编号" align="center" width="180" :show-overflow-tooltip="true"/>

      <el-table-column prop="drawing_name" label="材料名称" align="center" width="160" />

      <el-table-column prop="drawing_spec" label="规格/图纸号" align="center" width="180" :show-overflow-tooltip="true"/>
      <el-table-column prop="drawing_page" label="图纸页数" align="center" width="60" />
      <el-table-column prop="drawing_client_id" label="客户编号" align="center" width="180" :show-overflow-tooltip="true"/>
      <el-table-column prop="drawing_version" label="版本号" align="center" width="70" />
      <el-table-column prop="drawing_remark" label="备注" align="center" width="180" :show-overflow-tooltip="true"/>
      <el-table-column prop="modified" label="最后上传日期" align="center" width="160" />
      <el-table-column label="操作" align="center">
        <el-button type="primary" :icon="More" circle size="small"/>
        <el-button type="warning" :icon="Edit" circle size="small"/>
        <el-button type="danger" :icon="Delete" circle size="small"/>
      </el-table-column>
      </el-table>

2、axios请求优化(一)

如果每次调用接口都要输入一堆实在是太麻烦了,这里可以进行简化

在src根目录新建api文件如下:

image.png

新建utils文化如下:

image.png

src\utils\request.ts

// 导入




import axios from "axios";
​





// 创建一个Axios的app
const request = axios.create({
    baseURL:'http://localhost:8000/DrawingApi/v1/',
    timeout:5000
})
​
// 请求拦截器
​

// 响应拦截器
​
// 暴露
export default request

src\api\sensors.ts

// 导入




import request from "../utils/request";



​





// RESTful 有(获取所有,添加,获取某一个,修改,删除)



​



// 获取所有



const getAll = (params:any) => {



    // request



    return request({



        method:'get',



        url:'Sensors/',
        params



    })



}



​



// 添加



const add = (data:any) => {



    // request



    return request({



        method:'post',



        url:'Sensors/',
        data



    })



}



​




// 获取单一数据



const getOne = (id:any) => {



    // request



    return request({



        method:'get',



        url:'Sensors/${id}/',
    })



}



​



// 修改



const edit = (id:any,data:any) => {



    // request



    return request({



        method:'put',



        url:'Sensors/${id}/',
        data



    })



}



​



// 删除



const del = (id:any,data:any) => {



    // request



    return request({



        method:'delete',



        url:'Sensors/${id}/',
    })



}



​



// 暴露所有



export default{



    getAll,getOne,edit,add,del



}



src\api\projects.ts

// 导入




import request from "../utils/request";



​





// RESTful 有(获取所有,添加,获取某一个,修改,删除)



​



// 获取所有



const getAll = (params:any) => {



    // request



    return request({



        method:'get',



        url:'Projects/',
        params



    })



}



​



// 添加



const add = (data:any) => {



    // request



    return request({



        method:'post',



        url:'Projects/',
        data



    })



}



​




// 获取单一数据



const getOne = (id:any) => {



    // request



    return request({



        method:'get',



        url:'Projects/${id}/',
    })



}



​



// 修改



const edit = (id:any,data:any) => {



    // request



    return request({



        method:'put',



        url:'Projects/${id}/',
        data



    })



}



​



// 删除



const del = (id:any,data:any) => {



    // request



    return request({



        method:'delete',



        url:'Projects/${id}/',
    })



}



​



// 暴露所有



export default{



    getAll,getOne,edit,add,del



}



src\api\datas.ts

// 导入




import request from "../utils/request";



​





// RESTful 有(获取所有,添加,获取某一个,修改,删除)



​



// 获取所有



const getAll = (params:any) => {



    // request



    return request({



        method:'get',



        url:'Datas/',
        params



    })



}



​



// 添加



const add = (data:any) => {



    // request



    return request({



        method:'post',



        url:'Datas/',
        data



    })



}



​




// 获取单一数据



const getOne = (id:any) => {



    // request



    return request({



        method:'get',



        url:'Datas/${id}/',
    })



}



​



// 修改



const edit = (id:any,data:any) => {



    // request



    return request({



        method:'put',



        url:'Datas/${id}/',
        data



    })



}



​



// 删除



const del = (id:any,data:any) => {



    // request



    return request({



        method:'delete',



        url:'Datas/${id}/',
    })



}



​



// 暴露所有



export default{



    getAll,getOne,edit,add,del



}



src\api\drawings.ts

// 导入




import request from "../utils/request";



​





// RESTful 有(获取所有,添加,获取某一个,修改,删除)



​



// 获取所有



const getAll = (params:any) => {



    // request



    return request({



        method:'get',



        url:'Drawings/',
        params



    })



}



​



// 添加



const add = (data:any) => {



    // request



    return request({



        method:'post',



        url:'Drawings/',
        data



    })



}



​




// 获取单一数据



const getOne = (id:any) => {



    // request



    return request({



        method:'get',



        url:'Drawings/${id}/',
    })



}



​



// 修改



const edit = (id:any,data:any) => {



    // request



    return request({



        method:'put',



        url:'Drawings/${id}/',
        data



    })



}



​



// 删除



const del = (id:any,data:any) => {



    // request



    return request({



        method:'delete',



        url:'Drawings/${id}/',
    })



}



​



// 暴露所有



export default{



    getAll,getOne,edit,add,del



}



src\api\index.ts

// 导入所有api
import sensors from "./sensors";
import projects from "./projects";
import datas from "./datas";
import drawings from "./drawings";
​
// 封装暴露
export default{
    sensors,projects,datas,drawings,
}

引用可为:

image.png

效果还是一样的:

image.png

3、把对应信息填充到下拉框

由于我们api都写好了,那么直接调用就好了:

script区域:
// 获取所有传感器的信息
const getSensors = () => {
  return Api.sensors.getAll().then((res)=>{
    Data.sensorOptions = res.data;
  })
}
// 获取所有项目的信息
const getProjects = () => {
  return Api.projects.getAll().then((res)=>{
    Data.projectOptions = res.data;
  })
}
// 获取所有资料的信息
const getDatas = () => {
  return Api.datas.getAll().then((res)=>{
    Data.dataOptions = res.data;
  })
}
​
template 区域:
<!-- 1.查询区域 -->
      <el-form :inline="true" class="demo-form-inline" style="display: flex">
        <el-form-item label="查询条件:">
          <el-input v-model="Data.q_str" placeholder="请输入查询条件" clearable/>
        </el-form-item>
        <el-form-item label="传感器:">
          <el-select v-model="Data.sensorSelected" placeholder="请选择传感器" clearable filterable>
            <el-option 
            v-for="item in Data.sensorOptions"
            :key="item.id"
            :label="item.sensor_name"
            :value="item.id" />
          </el-select>
        </el-form-item>
        <el-form-item label="项目:">
          <el-select v-model="Data.projectSelected" placeholder="请选择项目" clearable filterable>
             <el-option 
            v-for="item in Data.projectOptions"
            :key="item.id"
            :label="item.project_name"
            :value="item.id" />
          </el-select>
        </el-form-item>
        <el-form-item label="资料:">
          <el-select v-model="Data.dataSelected" placeholder="请选择资料" clearable filterable>
            <el-option 
            v-for="item in Data.dataOptions"
            :key="item.id"
            :label="item.data_name"
            :value="item.id" />
          </el-select>
        </el-form-item>

对了 之前表格信息不全 进行补充

 <!-- 2.表格部分 -->

      <el-table :data="Data.drawing" border style="width: 100%" :header-cell-style="{ backgroundColor:'#409EFF',color:'#FFF',fontSize:'14px' }">

      <el-table-column label="序号" type="index" align="center" width="60" />

      <el-table-column prop="material_code" label="物料编号" align="center" width="180" :show-overflow-tooltip="true"/>

      <el-table-column prop="drawing_name" label="材料名称" align="center" width="160" />

      <el-table-column prop="data.project.sensor.sensor_name" label="所属传感器" align="center" width="80" :show-overflow-tooltip="true"/>
      <el-table-column prop="data.project.project_name" label="所属项目" align="center" width="80" :show-overflow-tooltip="true"/>
      <el-table-column prop="drawing_spec" label="规格/图纸号" align="center" width="180" :show-overflow-tooltip="true"/>
      <el-table-column prop="drawing_page" label="图纸页数" align="center" width="60" />
      <el-table-column prop="drawing_client_id" label="客户编号" align="center" width="100" :show-overflow-tooltip="true"/>
      <el-table-column prop="drawing_version" label="版本号" align="center" width="70" />
      <el-table-column prop="drawing_remark" label="备注" align="center" width="180" :show-overflow-tooltip="true"/>
      <el-table-column prop="modified" label="最后上传日期" align="center" width="160" />
      <el-table-column label="操作" align="center">
        <el-button type="primary" :icon="More" circle size="small"/>
        <el-button type="warning" :icon="Edit" circle size="small"/>
        <el-button type="danger" :icon="Delete" circle size="small"/>
      </el-table-column>
      </el-table>

效果为:

image.png

4、对树进行数据填充

这边树的处理是前端拼接的,理论上由后端进行处理传给前端,前端按照层级点击后进行加载。但是这里由于项目是我一个人编写,且未来项目其实数据量不会很大。所以我这里还是以项目跑起来为主,后期再优化

// 将数据拼接成树
const getTree = () => {
  Promise.all([getSensors(), getProjects(), getDatas()]).then(() => {
    // 组合
    for(let sensors of Data.sensorOptions){
    // 定义需要的结构
    var obj = reactive({
      value:`${sensors.id}-${sensors.sensor_name}`,
      label:sensors.sensor_name,
      children:[],
      depth: 1
    }) 
    // 遍历项目填充obj的children
    for(let project of Data.projectOptions){
      if(project.sensor.id === sensors.id){
        var obj1 = reactive({
          value:project.id,
          label:project.project_name,
          children:[],
          depth: 2
        });
        for(let data of Data.dataOptions){
          if(data.project.id === project.id){
            obj1.children.push({
              value:data.id,
              label:data.data_name,
              depth: 3
            });
          }
        }
        obj.children.push(obj1)
      }
    }
    Data.treeData.push(obj)
    }
  });
​
}
​
// 定义页面加载的时候自动执行的函数
const autoRun = () => {
  // 获取所有图纸信息
  getData();
  // 获取所有传感器的信息
  getSensors();
  getProjects();
  getDatas();
  getTree();
}
​
 <!-- 侧边栏 -->
      <div class="tree-container">
        <el-tree :data="Data.treeData" @node-click="nodeClick"></el-tree>
      </div>

效果为:

image.png

思考:这里如果通过树进行搜索的话,那我搜索的下拉框其实作用就不大了,且没有层级绑定。

image.png

这边暂时不进行修改,为了更好的展示项目知识点,方便今后其他项目需要进行修改。后期系统优化时候,再进行修改。

未完待续。。。

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYBb0PG3' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片