记vue+drf前后端分离学习过程(1)

本文介绍了在Vue和DjangoRestFramework(DRF)项目中处理前后端通讯的常见问题及解决方案,包括Vue的代理配置以避免跨域问题,axios的封装和使用,以及Django视图和序列化的实现。同时,提到了cookie的管理和联表查询的方法。

前言:

因为vue和drf都只是学了一些基础,所以对于一些用法不是很熟悉,遇到了很多困难,想再次记录一下困难的解决方法供我自己以后复盘,也让希望能帮助到看到这篇文章的人,会不定期更新。

困难:

  1. 前后端通讯:

我遇到的第一个困难就是前后端通讯问题,不过这个解决起来相对容易,我在这里也写一下

前端:
  1. 先在vue.config.js文件里面更改配置:

module.exports={
    devServer:{
        open: true,
        // ws: false,
        //代理配置
        proxy: {
            '/api': {
                target: 'http://127.0.0.1:8000',
                changeOrigin: true,
                pathRewrite: {
                    '^/api': ''
                }
            }
        }
    }
}

其中‘/api’的意思是当你的url中有/api的时候,就会把这个/api替换成target中的地址,也就是说,你的请求地址会变成http://

然后在src文件夹中添加文件夹api,在里面加入api.js

  1. 在src文件夹中添加service.js文件,编写:

//axios封装

import axios from "axios";
import { getToken } from '@/utils/Token.js'
import { Message } from "element-ui";

const service = axios.create({
    baseURL: '/api', //baseURL会自动加载到地址上
    timeout: 6000
})

//添加请求拦截器
service.interceptors.request.use((config) => {
    //在请求之前做些什么(获取并设置token)
    config.headers['token'] = getToken('token')
    return config
}, (error) => {
    return Promise.reject(error)
})


//添加响应拦截器
service.interceptors.response.use((response) => {
    //对响应数据做些什么
    let { status,message } = response
    if (status !== 200) {
        Message({ message: message || 'error', type: "warning" })
    }
    return response
}, (error) => {
    return Promise.reject(error)
})

export default service

这一步是使用的axios进行前后端通讯

  1. 在api中添加要使用的函数例如:

export function StudentManagement_crate(params) {
    return service({
        method: 'post',
        url: '/teacher/studentManagement/index',//这个地址为后端调用地址
        data:params
    })
}

export function ExperimentView(params) {
    return service({
        method: 'get',
        url: '/teacher/ExperimentView/index',
        params
    })
}
  1. 在需要使用后端调用的页面中使用如:

StudentManagement().then(res => {

            
            console.log(res.data);

            this.teacherschedulID = res.data;
        });

来进行后端调用。

后端:

后端使用django+drf进行接口的调用:

  1. 先在urls文件中进行路由分发,这样可以在自己的app里进行路由的配置比较方便:

    re_path(r'^teacher/', include('teacher.urls')),
  1. 然后我们在自己的app中新建一个urls.py的文件写成下面这样:

urlpatterns = [

   
    path('TeacherExperimentView/index', TeacherExperimentView.TeacherExperimentView.as_view()),
    path('TeacherExperimentView/<str:userID>/', TeacherExperimentView.TeacherExperimentView.as_view()),

]

这样一来我们只需要在这个文件中写路由即可

3.然后我们新建一个views文件夹,把view文件删掉,这样是方便在写view时可以更清晰,每个路由写一个py文件即可

文件中:

class fre_Experiment(serializers.ModelSerializer):
    class Meta:
        model = Experiment
        fields = "__all__"


class ExperimentView(ListCreateAPIView)://整体操作
    queryset = Experiment.objects.all()
    serializer_class = fre_Experiment


class ExperimentView_i(RetrieveUpdateDestroyAPIView)://单独操作如单独查询
    queryset = Experiment.objects.all()
    serializer_class = fre_Experiment

如果需要重写方法:

get:

#     def get(self, request, *args, **kwargs):
#         res = {
#             'code': 200,
#             'msg': '获取成功',
#             'data': None,
#         }
#         experiment_obj = Experiment.objects.all()#将表中所有内容拿出来
#
#         experiment_ser = fre_Experiment(experiment_obj, many=True)#将实验序列化,many=True表示多个
#         res['data'] = experiment_ser.data #将数据赋值给res.data
#         return Response(res)

post:

    def post(self, request, *args, **kwargs):
        res = {
            'code': 200,
            'msg': '创建成功',
            'data': None,
        }
#下面四行是将前端传过来的数据进行赋值:
        experiment_name = request.data.get('experiment_name')
        report = request.data.get('report')
        video_uri = request.data.get('video_uri')
        other = request.data.get('other')



        experiment_obj = Experiment.objects.create(experimentID=experimentID, experiment_name=experiment_name,
                                                   report=report, video_uri=video_uri, other=other)
        experiment_ser = fre_Experiment(experiment_obj)#序列化
        res['data'] = experiment_ser.data
        return Response(res)
这里说一中需要传参的情况,比如说找表中特定的一列:
前端:

在api中这样写:

//获取单个实验的详情信息,需要在url中拼接参数
export function StudentManagementDetail(params) {
    return service({
        method: 'get',
        url: '/teacher/ExperimentView/' + params.experimentID,
        params
    })
}

在页面文件中这样写:

//把experimentID改为对象
        const data = {
            experimentID: this.experimentID
        };
 
StudentManagementDetail(data).then(res => {
            console.log(res.data);
            this.experimentID = res.data;
        });
后端:

在urls文件中:

    re_path('ExperimentView/(?P<pk>\d+)', ExperimentView.ExperimentView_i.as_view()),

其中(?P<pk>\d+)即为传递的参数

在views文件夹中:

class ExperimentView_i(RetrieveUpdateDestroyAPIView):
    queryset = Experiment.objects.all()
    serializer_class = fre_Experiment

如果直接用drf的话这样即可,不需要自己手动更改

  1. cookie使用

vue使用cookie需要添加一个文件:

npm install mavon-editor --save

在main.js引入:


import VueCookies from"vue-cookies"
Vue.use(VueCookies);

添加:

this.$cookies.set('username', this.data.username)

使用:

this.$cookies.get('username')

删除:

 this.$cookies.remove('username');
  1. 关于后端联表查询的问题

  2. 外键查询

 使用drf进行联表查询时最简单的方法是在序列化的时候进行外键暴露:

views:

class TeacherExperimentSerializers(serializers.ModelSerializer):
    # # 外键暴露
    userID = serializers.StringRelatedField()
    experimentID = serializers.StringRelatedField()

    class Meta:
        model = TeacherExperiment
        fields = "__all__"

这样在查询的时候会直接将关联的数据覆盖到原本的数据上,使用起来会非常方便

但是有一个问题就是,如果即想要原数据又想要联表的数据就非常麻烦,

比如说我想要学生的学号,又想要学生对应学号的名称,就没有什么办法,这个时候可以用第二种方法

class TeacherExperimentSerializers(serializers.ModelSerializer):

    experiment_name = SerializerMethodField()
    def get_experiment_id(self, obj):
        return Experiment.objects.get(experimentID=obj.experimentID_id).experiment_name

    class Meta:
        model = TeacherExperiment
        fields = "__all__"

自定义一个字段(experiment_name)然后使用后面的get_experiment_id进行添加(一定要get_字段名称)

Experiment.objects.get(experimentID=obj.experimentID_id).experiment_name
“Experiment”:是需要添加的数据的表
“(experimentID=obj.experimentID_id)“:Experiment表中的experimentID字段和本表中“experimentID_id“字段相同的那个“experiment_name”
“experiment_name”:Experiment表中需要放入的字段名

这样在输出数据时就会输出指定的字段

中间表查询

        

class ProjectSerializer(serializers.ModelSerializer):
    members_names = serializers.SerializerMethodField()

    def get_members_names(self, obj):
        return [member.name for member in obj.members.all()]


    class Meta:
        model = Project
        fields = "__all__"

通过使用遍历中间表的方式进行搜索

基本是同上

return [member.name for member in obj.members.all()]

name为需要搜索的表的name字段

member为project表中定义的与中间表关联字段的名称

需要知道的是需要首先在表中设置好例如

members = models.ManyToManyField('Student', through='StudentProject', related_name='project_members')

即可

本季课程把开发知识拆解到项目里,让你在项目情境里学知识。这样的学习方式能让你保持兴趣、充满动力,时刻知道学的东西能用在哪、能怎么用。平时不明白的知识点,放在项目里去理解就恍然大悟了。  一、融汇贯通本视频采用了前后端分离的开发模式,前端使用Vue.js+Element UI实现了Web页面的呈现,后端使用Python 的Django REST Framework框架实现了数据访问的接口,前端通过Axios访问后端接口获得数据。在学习完本章节后,真正理解前后端的各自承担的工作。 二、贴近实战本课程为学生信息管理系统课程:Vue3 + Vite + ElementPlus + Django REST Framework项目实战 本季课程主学生信息管理系统V5.0,内容包含:Django REST framework安装和项目初始化、数据的序列化、ViewSet视图集、DefaultRouter路由类、django-filter实现过滤、rest framework实现查找、rest framework实现分页、npm的使用、使用Vite构建vue3项目、Package.json解析、ElementPlus安装和应用、vue-router实现路由、使用Vuex的store对象、后台管理系统主界面的布局、axios组件的安装和请求、axios请求的模块化、请求拦截器和响应拦截器、使用el-select实现联级下拉、使用cascader实现联级选择、vue表单的验证、实现学生信息的添加、修改和删除、实现文件的上传等等功能 本案例完整的演示了项目实现过程,虽然不复杂,但涉及的内容非常多,特别是前后端交互的时候,有诸多的坑等着你去踩,好在王老师全程代码呈现,带着大家一起填坑,大大提高学习效率的同时,也培养了大家良好的代码习惯,希望大家一起跟着王进老师学习Python开发。三、后续课程预告:Vue和Django REST Framework实现JWT登录认证 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值