Django后台数据获取展示

​ 续接Django REST Framework,使用Vite构建Vue3的前端项目

1.跨域获取后台接口并展示

  • 安装Axios
npm install axios --save
  • 前端查看后端所有定义的接口
// 访问后端定义的可视化Api接口文档
http://ip:8000/docs/
// 定义的学生类信息
http://ip:8000/api/v1/students/

  • 前端对后端发起请求
// 导入 axios
import axios from 'axios'

// 页面一加载便获取axios请求

<script>
    // 获取所有信息
    const getStudents = () => {
        // axios请求
        axios.get('http://192.168.20.110:8000/api/v1/students/').then((res)=>{
            // 请求成功
            console.log('成功',res)
        }).catch((error)=>{
            // 请求失败
            console.log('失败',error)
        })
    }
    // 定义页面加载时自动执行的函数
    const autoRun= () => {
        // 获取所有信息
        getStudents() 
    }
    // 调用自动执行函数执行
    autoRun() 
</script>
  • 后端配置运行环境

// 或者直接在0.0.0.0:8000下运行
python manage.py runserver 0.0.0.0:8000

// 后端开启跨域,安装组件
pip install django-cors-headers
// 注册
INSTALLED_APPS[
    'corsheaders'
]
// 添加到中间件中
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'corsheaders.middleware.CorsMiddleware',# 跨域请求
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
# ======跨域配置======
# 后端是否支持对 Cookis访问
CORS_ALLOW_CREDENTIALS = True
# 白名单地址
CORS_ORIGIN_WHITELIST = (
    'http://192.168.20.110:8080',
)

  • 跨域获取所有信息
// 导入 axios
import axios from 'axios'

// 添加信息获取提示
import { ElMessage } from 'element-plus'

// 页面一加载便获取axios请求

<script>
    // 获取所有信息
    const getStudents = () => {
        // axios请求
        axios.get('http://192.168.20.110:8000/api/v1/students/').then((res)=>{
            // 请求成功
            // console.log('成功',res)
            // 判断是否成功
            if (res.status==200){
                // 成功执行
                Data.students = res.data.results
                // 将记录总数绑定到分页的total
                Data.total = res.data.count
                ElMessage({
                    message: '数据加载成功!',
                    type: 'success',
                })
            }
        }).catch((error)=>{
            // 请求失败
            console.log('失败',error)
        })
    }
    // 定义页面加载时自动执行的函数
    const autoRun= () => {
        // 获取所有信息
        getStudents() 
    }
    // 调用自动执行函数执行
    autoRun() 
</script>

  • 分页优化
<script lang="ts" setup>
import { ref, reactive } from "vue"
import {More,Edit,Delete} from "@element-plus/icons-vue"
import axios from 'axios'
// 添加信息获取提示
import { ElMessage } from 'element-plus'


// 定义存储集合
var Data = reactive({
    // 定义输入的查询条件
    q_str: ref(""),
    // 存储从后台获取的所有院系信息
    FacultyOptions: reactive([
        {
            value:1,
            label:'计算机学院'
        },
        {
            value:2,
            label:'外语学院'
        },
    ]),
    // 存储选择院系后的值
    FacultySelected: ref(""),

     // 存储从后台获取的所有专业信息
     MajorOptions: reactive([
        {
            value:1,
            label:'计算机专业'
        },
        {
            value:2,
            label:'外语专业'
        },
    ]),
    // 存储选择专业后的值
    MajorSelected: ref(""),
    // ===表格区域定义====
    students: reactive([
        
    ]),
    // =====分页====
    // 当前页
    currentsPage: ref(1),
    // 每页显示的数据量
    pageSize: ref(15),
    // 总数据量所有记录条数
    total: ref(0),
});

// 分页中修改每页的pageSize
const handleSizeChange=(size: any)=>{
  // 修改记录条数
  Data.pageSize = size
  // 重新获取所有信息
  getStudents()
}

// 分页中修改每页的currentsPage
const handleCurrentChange=(page: any)=>{
  // 修改当前页
  Data.currentsPage = page
  // 重新获取所有信息
  getStudents()
}

// ======前后端交互======
// 获取所有信息
const getStudents = () => {
    // 定义一个集合存储分页参数
        let params = {
            page: Data.currentsPage,
            size: Data.pageSize
        }
        // axios请求
        axios.get('http://192.168.20.110:8000/api/v1/students/',{params:params}).then((res)=>{
            // 请求成功
            console.log('成功',res)
            // 判断是否成功
            if (res.status==200){
                // 成功执行
                Data.students = res.data.results
                // 将记录总数绑定到分页的total
                Data.total = res.data.count
                // 成功提示
                ElMessage({
                  message: '数据加载成功!',
                  type: 'success',
                })

            }
        }).catch((error)=>{
            // 请求失败
            console.log('失败',error)
        })
    }
    // 定义页面加载时自动执行的函数
    const autoRun= () => {
        // 获取所有信息
        getStudents() 
    }
    // 调用自动执行函数执行
    autoRun() 

</script>
  • 院系/专业信息展示优化

学生表里只记录了专业的id,专业表里记录了院系的id,要使在学生明细表中展示专业和院系信息则需要在后端序列化专业表和院系表

// serializer.py
# 导入模块
# models中的类与接口转换
from rest_framework import serializers
from studentweb.models import *

# 学院序列化类
class FacultySerializer(serializers.ModelSerializer):

    class Meta:
        model = Faculty
        fields = '__all__'

# 专业序列化类
class MajorSerializer(serializers.ModelSerializer):
    # 序列化学院id
    faculty = FacultySerializer()
    class Meta:
        model = Major
        fields = '__all__'

# 学生序列化类
class StudentSerializer(serializers.ModelSerializer):
    # 序列化专业信息
    major = MajorSerializer()
    class Meta:
        model = Student
        fields = '__all__'
// 专业的名字:major.name
// 院系的名字:major.faculty.name
{
      "sno": "950001",
      "major": {
        "id": 2,
        "faculty": {
          "id": 1,
          "name": "计算机学院"
        },
        "name": "计算机网络"
      },
      "name": "王晓宇",
      "gender": "男",
      "birthday": "2022-03-01",
      "mobile": "13099881122",
      "email": "wangxiaoyu@qq.com",
      "address": "上海市闵行区春都路88号",
      "image": ""
    },
  •  表格绑定展示
// 更改前端表格展示数据
 <el-table-column prop="major.faculty.name" label="院系" align="center" width="120" />
 <el-table-column prop="major.name" label="专业" align="center" width="120" />
  • 表格过长数据处理
// 过长信息不展示完全使用'...'显示

// 标签添加 :show-overflow-tooltip="true"属性

2.Axios模块化请求

  • request脚本实现
// 新建 /src/utils/request.ts
// 封装 axios代码实现模块化

// 1.导入
import axios from 'axios'
// 2.创建一个Axios的app
const request = axios.create({
    // 定义基本 URL
    baseURL: 'http://192.168.__.___:8000/api/v1/',
    // 设置超时
    timeout: 5000,
    
})

// 3.暴露
export default request 
// 添加request.ts配置的axios

<script lang="ts" setup>
// 导入request
import request from "../../utils/request";
import { ref, reactive } from "vue"
import {More,Edit,Delete} from "@element-plus/icons-vue"

// 添加信息获取提示
import { ElMessage } from 'element-plus'


// 定义存储集合
var Data = reactive({
    // 定义输入的查询条件
    q_str: ref(""),
    // 存储从后台获取的所有院系信息
    FacultyOptions: reactive([
        {
            value:1,
            label:'计算机学院'
        },
        {
            value:2,
            label:'外语学院'
        },
    ]),
    // 存储选择院系后的值
    FacultySelected: ref(""),

     // 存储从后台获取的所有专业信息
     MajorOptions: reactive([
        {
            value:1,
            label:'计算机专业'
        },
        {
            value:2,
            label:'外语专业'
        },
    ]),
    // 存储选择专业后的值
    MajorSelected: ref(""),
    // ===表格区域定义====
    students: reactive([
        
    ]),
    // =====分页====
    // 当前页
    currentsPage: ref(1),
    // 每页显示的数据量
    pageSize: ref(15),
    // 总数据量所有记录条数
    total: ref(0),
});

// 分页中修改每页的pageSize
const handleSizeChange=(size: any)=>{
  // 修改记录条数
  Data.pageSize = size
  // 重新获取所有信息
  getStudents()
}

// 分页中修改每页的currentsPage
const handleCurrentChange=(page: any)=>{
  // 修改当前页
  Data.currentsPage = page
  // 重新获取所有信息
  getStudents()
}

// ======前后端交互======
// 获取所有信息
const getStudents = () => {
    // 定义一个集合存储分页参数
        let params = {
            page: Data.currentsPage,
            size: Data.pageSize
        }
        // axios请求
        request.get('students/',{params:params}).then((res)=>{
            // 请求成功
            console.log('成功',res)
            // 判断是否成功
            if (res.status==200){
                // 成功执行
                Data.students = res.data.results
                // 将记录总数绑定到分页的total
                Data.total = res.data.count
                // 成功提示
                ElMessage({
                  message: '数据加载成功!',
                  type: 'success',
                })

            }
        }).catch((error)=>{
            // 请求失败
            console.log('失败',error)
        })
    }
    // 定义页面加载时自动执行的函数
    const autoRun= () => {
        // 获取所有信息
        getStudents() 
    }
    // 调用自动执行函数执行
    autoRun() 

</script>
  • Api数据集及请求类型以及url优化 接口实现
// 新建 /src/api/students.ts(majors.ts/facultys.ts)

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

// RESTFUL ---> 6个接口【获取所有,添加,获取某一个,修改,删除】

// ====获取所有====
const getAll = (params ?: any) => {
    // request
    return request({
        method: "GET",
        url: "/students",
        params,
    })
}

// ====添加====
const add= (data: any) => {
    // request
    return request({
        method: "POST",
        url: "/students",
        data,
    })
}
// ====获取单一数据====
const getOne=(id: any) => {
    // request
    return request({
        method: "GET",
        url: `/students/${id}`,
    })
}
// ====修改====
const edit=(id: any, data: any) => {
    // request
    return request({
        method: "PUT",
        url: `/students/${id}`,
        data
    })
}
// ====删除====
const del = (id: any) => {
    // request
    return request({
        method: "DELETE",
        url: `/students/${id}`,
    })
}
export default {
    getAll,
    add,
    getOne,
    edit,
    del,
    // 也可以直接在此处定义其他的 api
}

// 新建 index.ts用于导入所有api

// 导入所有
import studentApi from "./students"
import majorsApi from "./majors"
import facultysApi from "./facultys"

// 封装并发布
export default {
    studentApi,
    majorsApi,
    facultysApi,    
}

// 使用 上述定义的接口

<script lang="ts" setup>
import { ref, reactive } from "vue"
import {More,Edit,Delete} from "@element-plus/icons-vue"
// 导入API
import indexApi from '../../api/index'
// 添加信息获取提示
import { ElMessage } from 'element-plus'


// 定义存储集合
var Data = reactive({
    // 定义输入的查询条件
    q_str: ref(""),
    // 存储从后台获取的所有院系信息
    FacultyOptions: reactive([
        {
            value:1,
            label:'计算机学院'
        },
        {
            value:2,
            label:'外语学院'
        },
    ]),
    // 存储选择院系后的值
    FacultySelected: ref(""),

     // 存储从后台获取的所有专业信息
     MajorOptions: reactive([
        {
            value:1,
            label:'计算机专业'
        },
        {
            value:2,
            label:'外语专业'
        },
    ]),
    // 存储选择专业后的值
    MajorSelected: ref(""),
    // ===表格区域定义====
    students: reactive([
        
    ]),
    // =====分页====
    // 当前页
    currentsPage: ref(1),
    // 每页显示的数据量
    pageSize: ref(15),
    // 总数据量所有记录条数
    total: ref(0),
});

// 分页中修改每页的pageSize
const handleSizeChange=(size: any)=>{
  // 修改记录条数
  Data.pageSize = size
  // 重新获取所有信息
  getStudents()
}

// 分页中修改每页的currentsPage
const handleCurrentChange=(page: any)=>{
  // 修改当前页
  Data.currentsPage = page
  // 重新获取所有信息
  getStudents()
}

// ======前后端交互======
// 获取所有信息
const getStudents = () => {
    // 定义一个集合存储分页参数
        let params = {
            page: Data.currentsPage,
            size: Data.pageSize
        }
        // axios请求
        indexApi.studentApi.getAll(params).then((res)=>{
            // 请求成功
            console.log('成功',res)
            // 判断是否成功
            if (res.sta
<think>好的,我现在需要帮助用户将之前的JavaScript ECharts代码与Django后台集成,使用Python获取数据。用户之前已经得到了关于如何优化前端代码的建议,现在他们想了解如何从Django后端获取数据来动态更新图表。 首先,我要确定用户的需求。他们可能已经有一个Django项目,现在需要后端提供数据前端的ECharts图表。用户可能对Django的MTV模式不太熟悉,或者不清楚如何将数据从视图传递到模板。 接下来,我需要考虑如何构造回答。可能需要分步骤讲解:创建Django视图、配置URL、模板渲染数据,以及前端的Ajax请求。用户可能需要具体的代码示例,所以需要提供详细的代码片段,并解释每个部分的作用。 还要注意用户提到的使用PythonDjango后台获取数据,这可能包括如何从数据库查询数据,并将其转换为JSON格式。可能需要提到使用Django的模型和ORM,比如通过models定义数据模型,然后在视图中查询数据。 另外,用户之前的前端代码中使用的是JavaScript变量v1和v2,现在需要将这些变量替换为从后端获取数据。需要解释如何在模板中使用Django的模板变量,或者通过Ajax动态获取数据,后者更适合实时更新。 可能还需要提到安全性问题,比如CSRF保护,当使用POST请求获取数据时,需要处理CSRF token。不过,如果是GET请求,可能不需要,但最好还是提到这一点。 另外,用户可能需要图表在页面加载时自动获取数据,或者在某个事件触发时更新。需要给出两种方式的示例,比如页面加载时初始化,以及通过按钮点击刷新数据。 还需要考虑数据格式,确保后端返回的数据结构符合前端ECharts的要求。例如,返回一个包含v1和v2的JSON对象,前端解析后更新图表。 最后,要确保整个流程清晰,步骤明确,用户能够按照步骤一步步实现集成。可能需要检查是否有遗漏的步骤,比如URL配置是否正确,视图函数是否正确处理请求,以及前端是否正确处理响应。</think>以下是基于 Django 后端 + 前端 ECharts 的完整数据集成方案,分为 **Python 后端**和 **前端 JavaScript** 两部分实现: --- ### **一、Django 后端实现** #### 1. 定义数据模型 (models.py) ```python from django.db import models class RepairRecord(models.Model): STATUS_CHOICES = [ ('closed', '已结算'), ('open', '未结算') ] status = models.CharField(max_length=10, choices=STATUS_CHOICES) created_at = models.DateTimeField(auto_now_add=True) ``` #### 2. 编写视图函数 (views.py) ```python from django.http import JsonResponse from .models import RepairRecord def get_repair_rate(request): # 从数据库统计数据 closed_count = RepairRecord.objects.filter(status='closed').count() open_count = RepairRecord.objects.filter(status='open').count() # 计算闭环率 total = closed_count + open_count close_rate = round((closed_count / total * 100), 2) if total > 0 else 0 # 返回JSON数据 return JsonResponse({ 'v1': closed_count, 'v2': open_count, 'close_rate': close_rate }) ``` #### 3. 配置路由 (urls.py) ```python from django.urls import path from . import views urlpatterns = [ path('api/repair-rate/', views.get_repair_rate, name='repair-rate-api'), ] ``` --- ### **二、前端集成方案** #### 1. 基础模板渲染 (HTML) ```html <div id="echart2" style="width: 600px; height: 400px;"></div> <script> // 直接从Django模板变量初始化(适用于首屏加载) var initialData = {{ repair_data|safe }}; // 需要在视图中传递context </script> ``` #### 2. 动态Ajax请求(推荐方式) ```javascript function echarts_2() { // 初始化图表 var myChart = echarts.init(document.getElementById('echart2')); // 发起Ajax请求获取数据 fetch('/api/repair-rate/') .then(response => response.json()) .then(data => { var option = { series: [{ type: 'pie', data: [ {value: data.v1, name: '已结算'}, {value: data.v2, name: '未结算'} ], label: { formatter: data.close_rate + '%' } }] }; myChart.setOption(option); }); // 窗口自适应 window.addEventListener("resize", () => myChart.resize()); } ``` --- ### **三、Django视图数据传递(可选方案)** #### 1. 服务端渲染方式 (views.py) ```python from django.shortcuts import render def dashboard(request): closed = RepairRecord.objects.filter(status='closed').count() open = RepairRecord.objects.filter(status='open').count() return render(request, 'dashboard.html', { 'repair_data': { 'v1': closed, 'v2': open, 'close_rate': round(closed / (closed + open) * 100, 2) } }) ``` #### 2. 模板中使用 (dashboard.html) ```javascript var myChart = echarts.init(document.getElementById('echart2')); var option = { series: [{ data: [ {value: {{ repair_data.v1 }}, name: '已结算'}, {value: {{ repair_data.v2 }}, name: '未结算'} ] }] }; myChart.setOption(option); ``` --- ### **四、关键技术点说明** 1. **数据流架构** $$ \text{数据库} \rightarrow \text{Django ORM} \rightarrow \text{JSON API} \rightarrow \text{ECharts} $$ 2. **性能优化建议** - 添加数据库查询缓存: ```python from django.core.cache import cache def get_repair_rate(request): cache_key = 'repair_stats' data = cache.get(cache_key) if not data: # ...数据库查询... cache.set(cache_key, data, timeout=300) # 缓存5分钟 return JsonResponse(data) ``` - 使用 `select_related`/`prefetch_related` 优化关联查询 3. **安全增强** - 添加API访问频率限制: ```python from django.views.decorators.cache import cache_page @cache_page(60 * 5) # 5分钟缓存 def get_repair_rate(request): # ... ``` - 启用CORS头部(如果跨域) --- ### **五、扩展应用场景** 1. **实时更新** 通过WebSocket实现数据推送: ```python # consumers.py from channels.generic.websocket import AsyncWebsocketConsumer class RepairStatsConsumer(AsyncWebsocketConsumer): async def connect(self): await self.accept() while True: data = get_live_data() # 自定义数据获取 await self.send(json.dumps(data)) await asyncio.sleep(60) # 每分钟推送 ``` 2. **历史趋势图** 添加时间范围查询参数: ```python # views.py def get_repair_rate(request): start_date = request.GET.get('start') end_date = request.GET.get('end') queryset = RepairRecord.objects.all() if start_date and end_date: queryset = queryset.filter(created_at__range=[start_date, end_date]) # ... ``` --- 通过以上方案,可以实现从 Django 数据库到 ECharts 可视化图表的完整数据链路。具体选择服务端渲染还是 API 动态加载,可根据项目的实时性要求决定。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值