续接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