在我这个项目中,暂时没有实用性。因为最终我决定还是把这两个表格分开来展示和编辑。但,可能在其它地方可以用到呢?
一,Django数据库Model
见上一篇,https://www.jianshu.com/p/eb2ea9807c59
指标通过外键关联指标集。
二,DRF序列化文件
from rest_framework import serializers
from MetisModels.models import ViewSet
from MetisModels.models import Attr
class ViewSetSerializer(serializers.ModelSerializer):
class Meta:
model = ViewSet
# fields = '__all__'
fields = ['id', 'view_id', 'view_name', 'update_date']
extra_kwargs = {
'update_date': {
'read_only': True,
}
}
class AttrSerializer(serializers.ModelSerializer):
class Meta:
model = Attr
# fields = '__all__'
fields = ['id', 'attr_id', 'attr_name', 'update_date']
extra_kwargs = {
'update_date': {
'read_only': True,
}
}
这里只实现了显示的功能,update_date的更新,由django自已的机制实现,不参与参数传递。
三,DRF过滤器文件
from django_filters.rest_framework import FilterSet
from django_filters import filters
from MetisModels.models import ViewSet
from MetisModels.models import Attr
class ViewSetFilter(FilterSet):
view_name = filters.CharFilter(field_name='view_name', lookup_expr='icontains')
class Meta:
model = ViewSet
fields = ['view_name']
class AttrFilter(FilterSet):
attr_name = filters.CharFilter(field_name='attr_name', lookup_expr='icontains')
class Meta:
model = Attr
fields = ['attr_name']
越用越觉得这个django_filters好用,大约就是熟能生巧咯~~~多这个功能不多,少这个功能怕以后就麻烦了。
四,DRF的请求视图
from MetisModels.models import ViewSet
from MetisModels.models import Attr
from .serializers import ViewSetSerializer
from .serializers import AttrSerializer
from rest_framework.generics import ListAPIView
from rest_framework.filters import OrderingFilter, SearchFilter
from django_filters.rest_framework import DjangoFilterBackend
from config.error_code import *
from utils.utils import build_ret_data, render_json
from utils.pagination import PNPagination
from utils.filters import ViewSetFilter
from utils.filters import AttrFilter
class ViewSetListView(ListAPIView):
queryset = ViewSet.objects.all()
serializer_class = ViewSetSerializer
pagination_class = PNPagination
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
filter_class = ViewSetFilter
ordering_fields = ['id']
def get(self, request, *args, **kwargs):
res = super().get(self, request, *args, **kwargs)
return_dict = build_ret_data(OP_SUCCESS, res.data)
return render_json(return_dict)
class AttrListView(ListAPIView):
pagination_class = PNPagination
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
filter_class = AttrFilter
ordering_fields = ['id']
def get(self, request, *args, **kwargs):
query_params = request.query_params
print(query_params)
view_set_id = query_params.get('viewSetId')
attr_sets = Attr.objects.filter(view_set__id=view_set_id)
# 创建分页对象
pg = PNPagination()
# 在数据库中获取分页数据
pager_tasks = pg.paginate_queryset(queryset=attr_sets, request=request, view=self)
# 对分页数据进行序列化
serializer = AttrSerializer(instance=pager_tasks, many=True)
# 不带分页时,直接输出
# serializer = TrainTaskSerializer(instance=task_sets, many=True)
# print(serializer.data)
return_dict = build_ret_data(OP_SUCCESS, serializer.data)
return render_json(return_dict)
这个视图写好了,对于理解django原生的视图,也是有绝对好处的,多使用。
分页文件没有讲,因为它上一个文章里讲的一样。
五,antd vue的数据
data () {
return {
outerColumns: [
{ title: '指标集ID', dataIndex: 'id', key: 'id' },
{ title: '指标集', dataIndex: 'viewName', key: 'viewName' },
{ title: '更新时间', dataIndex: 'updateDate', key: 'updateDate' },
{ title: 'Action', key: 'operation', scopedSlots: { customRender: 'operation' } }
],
innerColumns: [
{ title: '指标ID', dataIndex: 'id', key: 'id' },
{ title: '指标', dataIndex: 'attrName', key: 'attrName' },
{ title: '更新时间', dataIndex: 'updateDate', key: 'updateDate' },
{
title: '',
dataIndex: 'operation',
key: 'operation',
scopedSlots: { customRender: 'operation' },
},
],
outerData: [],
pagination: {
'total': 0,
'pageSize': 10,
'currentPage': 1,
onChange: page => {
const pager = { ...this.pagination };
pager.currentPage = page;
this.pagination = pager;
this.fetch(this.pagination);
},
},
loading: false,
}
},
转到前端来,data里的主要数据,是定义outerData,而innerData只是outerData里的一个字段。
母表格和子表格的Columns,则须单独定义。
六,antd vue中的方法
fetch(params={}) {
this.loading = true;
getViewSetList(params).then(resp => {
let retData = resp.data
if (retData.code == 0) {
this.outerData = []
const results = retData.data.results
for (let i = 0; i < results.length; i++) {
this.outerData.push({
key: i,
id: results[i].id,
viewId: results[i].view_id,
viewName: results[i].view_name,
innerData: [],
updateDate: results[i].update_date
})
}
const pager = { ...this.pagination };
pager.total = retData.data.count;
this.pagination = pager;
this.loading = false;
} else {
this.loading = false;
this.$message.error(createRes.message, 3)
}
}).then(() => {
for (let i = 0; i < this.outerData.length; i++) {
const viewSetId = this.outerData[i].id
let innerData = []
getAttrList(viewSetId).then(resp => {
let retData = resp.data
if (retData.code == 0) {
const results = retData.data
for (let i = 0; i < results.length; i++) {
innerData.push({
key: viewSetId*10 + i,
id: results[i].id,
attrId: results[i].attr_id,
attrName: results[i].attr_name,
updateDate: results[i].update_date
})
}
this.outerData[i].innerData = innerData
} else {
this.loading = false;
this.$message.error(createRes.message, 3)
}
})
}
})
},
fetch()方法,主要用于构建outerData这个数据。先请求指标集,然后,再通过每个指标集的ID,去请求其下所有的子标。
按promise的套路,要使用then的链式方法来作才行。这也是我这个文章的重要知识点。我试过在getViewSetList()的for循环里,再请求getAttrList(),数据是不能传出来的。而通过then()的链式方法,就可以共同操作this.data里的数据,方便构造this.outterData的数据。
七,antd vue中的表格
两个