前言:
因为vue和drf都只是学了一些基础,所以对于一些用法不是很熟悉,遇到了很多困难,想再次记录一下困难的解决方法供我自己以后复盘,也让希望能帮助到看到这篇文章的人,会不定期更新。
困难:
-
前后端通讯:
我遇到的第一个困难就是前后端通讯问题,不过这个解决起来相对容易,我在这里也写一下
前端:
-
先在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
-
在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进行前后端通讯
-
在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
})
}
-
在需要使用后端调用的页面中使用如:
StudentManagement().then(res => {
console.log(res.data);
this.teacherschedulID = res.data;
});
来进行后端调用。
后端:
后端使用django+drf进行接口的调用:
-
先在urls文件中进行路由分发,这样可以在自己的app里进行路由的配置比较方便:
re_path(r'^teacher/', include('teacher.urls')),
-
然后我们在自己的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的话这样即可,不需要自己手动更改
-
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');
-
关于后端联表查询的问题
-
外键查询
使用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')
即可