ant design vue admin框架中,通过多个关联axios请求,实现母子嵌套表格

在我这个项目中,暂时没有实用性。因为最终我决定还是把这两个表格分开来展示和编辑。但,可能在其它地方可以用到呢?

一,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中的表格

    
编辑 编辑 删除 操作

两个嵌套起来,各自指定data-source和columns等属性,实现母子表格嵌套。

八,效果图

2020-12-12 13_38_09-.png

你可能感兴趣的:(ant design vue admin框架中,通过多个关联axios请求,实现母子嵌套表格)