bootstrap-table+Django: 服务端分页(包括搜索查询功能)

bootstrap-table+Django: 服务端分页(包括搜索查询功能)

1.分页方式:

bootstrap-table提供两种分页方式,client和server,即客户端和服务端分页;

特点:

  • client端分页:后台返回所有数据,前台翻页时不再请求后台。
  • server端分页:后台根据前台每次翻页时传递的参数,进行切片查询数据,每次只返回对应页面的数据。

弊端:

client端分页:

  1. 后台一次查询所有数据,对服务器造成压力交大;
  2. 当页面存在bootstrap-switch时,由于我是在bootstrap-table中的onLoadSuccess加载完表格后渲染switch开关,
  3. 当使用client分页时,只进行了一次后台查询,也就是执行了一次onLoadSuccess函数,所以除了第一页开关按钮正常,其他页面都没有渲染出开关。

server端分页:
    暂无

2.实现代码:

2.1 前端

在你的base模板中引入相应的包即可使用,这里代码就不全贴出来了

{% extends "base.html" %}
{% load static %}
{% block main %}
    <style>
        .table th, .table td {
            text-align: center;
            vertical-align: middle !important;
            word-break: break-all;
        }
    </style>
    <!-- Basic Setup -->
    <section class="section">
        <div class="container mt-100">
            <div class="row justify-content-center">
                <div class="col-12 text-center">
                    <div class="section-title mb-4 pb-2">
                        <h4 class="title mb-4">xxxxxxxx列表</h4>
                    </div>
                </div><!--end col-->
            </div><!--end row-->

            <div id="toolbar">
                <div class="form-inline" role="form">
                    <input class="btn btn-soft-primary btn-sm" type="button" id="btn1" value="显示所有列"
                           onclick="showAllCol()">
                    <a href="{% url 'feature_extension:new_feature' %}" target="_blank"  style="margin-left: 5px"><input
                            class="btn btn-soft-secondary btn-sm" type="button" id="btn2" value="增加新申请"
                            href="{% url 'feature_extension:new_feature' %}"></a>
                    <!-- 自定义搜索查询 -->
                    <div class="input-group" style="left: 5px"><input id="search-keyword"
                                                                       class="form-control search-input" type="search"
                                                                       placeholder="Search" autocomplete="off">
                        <div class="input-group-append">
                            <button id="search-button" class="btn btn-soft-primary btn-sm" type="button" name="search"
                                    title="Search">
                                <i class="fa fa-search"></i></button>
                        </div>
                    </div>
                </div>
            </div>
            <!-- data feature index pagination -->
            <table id="table"
                   class="table-sm small"
                   data-pagination="true"
                   data-buttons-class="soft-primary btn-sm"
                   data-sort-name="created_date"
                   data-sort-order="desc"
                   data-remember-order="true"

                   data-show-fullscreen="true"
                   data-show-columns="true"
                   data-show-columns-toggle-all="true"
                   data-show-export="true"

                   data-click-to-select="true"
                   data-toolbar="#toolbar"
                   style="table-layout: fixed;height: auto"
            >
                <thead class="thead-light">
            </table>
        </div>
    </section>
{% endblock %}

{% block script %}
    <!-- JS for download table-->
    <script>
        var $table = $('#table')
        $(function () {
            $('#toolbar').find('select').change(function () {
                $table.bootstrapTable('destroy').bootstrapTable({
                    exportDataType: $(this).val(),
                    exportTypes: ['excel', 'xml', 'csv', 'txt', 'sql'],
                    columns: [
                        {
                            field: 'state',
                            checkbox: true,
                            visible: $(this).val() === 'selected'
                        }
                    ]
                })
            }).trigger('change')
        })
    </script>
    <!-- JS for pagination -->
    <script>
        var $articlesTable = $('#table').bootstrapTable('destroy').bootstrapTable({
            url: '/feature_extension/feature_extension_list/',
            method: 'GET',
            dataType: "json",
            uniqueId: 'id',  //每一行的唯一标识,一般为主键列
            striped: false,  //是否显示行间隔色
            cache: false,
            sortName: 'no',
            sortable: true,
            sortOrder: 'desc',
            sidePagination: "server",
            undefinedText: '--',
            singleSelect: true,
            toolbar: '#toolbar',  //工具按钮用哪个容器
            showToggle: true,    //是否显示详细视图和列表视图的切换按钮
            cardView: false,    //是否显示详细视图
            strictSearch: true,
            clickToSelect: true,
            pagination: true,  //是否显示分页(*)
            showRefresh: true,  //是否显示刷新按钮
            pageNumber: 1,  //初始化加载第一页,默认第一页
            pageSize: 10,  //每页的记录行数(*)
            pageList: [10, 20, 50, 100, 'all'],
            paginationPreText: "<",
            paginationNextText: ">",
            queryParamsType: "",
            queryParams: function (params) {
                var query_params = {
                    'pageSize': params.pageSize,
                    'pageNumber': params.pageNumber,
                    'search_kw': $('#search-keyword').val(), // 查询框中的参数传递给后台
                    'sortName': params.sortName,
                    'sortOrder': params.sortOrder
                };
                return query_params;
            },
            columns: [
                {
                    field: 'no',
                    title: '序号',
                    align: 'center',
                    halign: 'center',
                    width: '60px',
                    visible: true,
                    sortable: true,
                    formatter: function (value, row, index) {
                        var result = "";
                        result += '+ row.id + '/" target="_blank">' + row.no + ''
                        return result
                    }
                },
                {
                    field: 'id',
                    title: 'DB_Id',
                    align: 'center',
                    halign: 'center',
                    width: '70px',
                    visible: false,
                    sortable: true,
                    formatter: function (value, row, index) {
                        var result = "";
                        result += '+ row.id + '/" target="_blank">' + row.id + ''
                        return result
                    }
                },
                {
                    field: 'title',
                    title: '主题',
                    align: 'left',
                    halign: 'center',
                    width: '180px',
                    visible: true,
                    formatter: function (value, row, index) {
                        var result = "";
                        result += '+ row.id + '/" target="_blank">' + row.title + ''
                        return result
                    }
                },
                {
                    field: 'owner',
                    title: '申请人ID',
                    align: 'left',
                    halign: 'center',
                    width: '100px',
                    visible: false,
                },
                {
                    field: 'full_name',
                    title: '申请人',
                    align: 'left',
                    halign: 'center',
                    width: '100px',
                    visible: true,
                },
                {
                    field: 'category',
                    title: '类别',
                    align: 'left',
                    halign: 'center',
                    width: '80px',
                    visible: true,
                },
                {
                    field: 'description',
                    title: '描述',
                    align: 'left',
                    halign: 'center',
                    width: '100px',
                    visible: false,
                },
                {
                    field: 'oecc_domestic',
                    title: 'OCL国内',
                    align: 'left',
                    halign: 'center',
                    width: '100px',
                    visible: false,
                    formatter: function (value, row, index) {
                        var result = "";
                        for (var i = 0; i < row.oecc_domestic.length; i++) {
                            result += ''+row.oecc_domestic[i].name+'; '
                        }
                        return result
                    }
                },
                {
                    field: 'oecc_oversea',
                    title: 'OCL海外',
                    align: 'left',
                    halign: 'center',
                    width: '100px',
                    visible: false,
                    formatter: function (value, row, index) {
                        var result = "";
                        for (var i = 0; i < row.oecc_oversea.length; i++) {
                            result += ''+row.oecc_oversea[i].name+'; '
                        }
                        return result
                    }
                },
                {
                    field: 'oe_domestic',
                    title: 'OE国内',
                    align: 'left',
                    halign: 'center',
                    width: '100px',
                    visible: false,
                    formatter: function (value, row, index) {
                        var result = "";
                        for (var i = 0; i < row.oe_domestic.length; i++) {
                            result += ''+row.oe_domestic[i].name+'; '
                        }
                        return result
                    }
                },
                {
                    field: 'oe_oversea',
                    title: 'OE海外',
                    align: 'left',
                    halign: 'center',
                    width: '100px',
                    visible: false,
                    formatter: function (value, row, index) {
                        var result = "";
                        for (var i = 0; i < row.oe_oversea.length; i++) {
                            result += ''+row.oe_oversea[i].name+'; '
                        }
                        return result
                    }
                },
                {
                    field: 'note',
                    title: '备注',
                    align: 'left',
                    halign: 'center',
                    width: '100px',
                    visible: false,
                },
                {
                    field: 'tech_ss',
                    title: '受影响子系统',
                    align: 'left',
                    halign: 'center',
                    width: '100px',
                    visible: true,
                    formatter: function (value, row, index) {
                        var result = "";
                        for (var i = 0; i < row.tech_ss.length; i++) {
                            result += ''+row.tech_ss[i].name+'; '
                        }
                        return result
                    }
                },
                {
                    field: 'solution',
                    title: '技术可行性',
                    align: 'left',
                    halign: 'center',
                    width: '100px',
                    visible: false,
                },
                {
                    field: 'complexity',
                    title: '复杂度',
                    align: 'left',
                    halign: 'center',
                    width: '100px',
                    visible: false,
                },
                {
                    field: 'tech_comment',
                    title: '技术团队建议',
                    align: 'left',
                    halign: 'center',
                    width: '100px',
                    visible: true,
                },
                {
                    field: 'mkt_decision',
                    title: '市场部决策',
                    align: 'left',
                    halign: 'center',
                    width: '100px',
                    visible: false,
                    formatter: function (value, row, index) {
                        {#console.log(row)#}
                        var result = "";
                        {#for (var i = 0; i < row.tech_ss.length; i++) {#}
                        {#    result += ''+row.tech_ss[i].name+'; '#}
                        {#}#}
                        return result
                    }
                },
                {
                    field: 'mkt_priority',
                    title: '优先级',
                    align: 'left',
                    halign: 'center',
                    width: '100px',
                    visible: false,
                },
                {
                    field: 'mkt_comment',
                    title: '市场团队建议',
                    align: 'left',
                    halign: 'center',
                    width: '100px',
                    visible: true,
                },
                {
                    field: 'status',
                    title: '进度状态',
                    align: 'center',
                    halign: 'center',
                    width: '80px',
                    visible: true,
                },
                {
                    field: 'plan',
                    title: '计划发布时间',
                    align: 'left',
                    halign: 'center',
                    width: '100px',
                    visible: false,
                },
                {
                    field: 'exe_owner',
                    title: '项目负责人',
                    align: 'left',
                    halign: 'center',
                    width: '100px',
                    visible: false,
                },
                {
                    field: 'exe_owner_mail',
                    title: '邮箱',
                    align: 'left',
                    halign: 'center',
                    width: '100px',
                    visible: false,
                },
                {
                    field: 'exe_leader_mail',
                    title: '经理邮箱',
                    align: 'left',
                    halign: 'center',
                    width: '100px',
                    visible: false,
                },
                {
                    field: 'cr_number',
                    title: 'CR',
                    align: 'left',
                    halign: 'center',
                    width: '100px',
                    visible: false,
                },
                {
                    field: 'cn_number',
                    title: 'CN',
                    align: 'left',
                    halign: 'center',
                    width: '100px',
                    visible: false,
                },
                {
                    field: 'mrd_date',
                    title: 'MRD',
                    align: 'left',
                    halign: 'center',
                    width: '100px',
                    visible: false,
                },
                {
                    field: 'created_date',
                    title: '创建日期',
                    align: 'center',
                    halign: 'center',
                    width: '100px',
                    visible: true,
                    sortable: true,
                },
                {
                    field: 'attachments',
                    title: '附件',
                    align: 'left',
                    halign: 'center',
                    width: '100px',
                    visible: false,
                    formatter: function (value, row, index) {
                        var result = "";
                        for (var i = 0; i < row.attachments.length; i++) {
                            result += '+ row.attachments[i].id + '">' + row.attachments[i].filename + ';
' } return result } }, { title: '操作', align: 'center', halign: 'center', width: '50px', visible: true, formatter: function (value, row, index) { var result = ""; result += '+ row.id + '/" target="_blank">   ' result += '+ row.id + ')">' return result } } ], onLoadError: function (data) { console.log("数据加载失败!", "错误提示"); $.messager.alert({title: '提示', msg: '数据加载失败!', icon: 'warning', top: 200}); }, }); // 搜索查询按钮触发事件 $("#search-button").click(function () { console.log($('#search-keyword').val()) $('#table').bootstrapTable(('refresh')); }) // 回车执行搜索 $("#search-keyword").bind('keyup', function (event) { console.log($('#search-keyword').val()) $('#table').bootstrapTable(('refresh')); }) </script> <!-- JS for delete data --> <script> function del_feature_ext(feature_id) { console.log(feature_id) $.messager.confirm({ title: '提示', msg: '是否确认删除该条数据?', top: 200, fn: function (r) { if (r) { $.ajax({ url: server_url + '/feature_extension/del_feature/' + feature_id, method: 'GET', processData: false, contentType: false, cache: false, success: function (data) { console.log("data:" + data); console.log("data:" + data.status); if (data.status === 200) { {#$.messager.alert({title: '提示', msg: data.msg, icon: 'warning', top: 200,});#} $.messager.show({ title: '提示', msg: data.msg, showType: '', timeout: 500, style: {top: 200} }); console.log("data:" + data.msg); {#window.setTimeout(window.location = server_url + '/cp_index/', 2500);#} window.setTimeout("window.location=server_url+'/feature_extension'", 600); return } console.log(data) $.messager.alert({title: '提示', msg: '权限不足或服务请求异常,数据无法删除!', icon: 'warning', top: 200}); }, //请求失败,包含具体的错误信息 error: function (data) { console.log('error' + data.msg); $.messager.alert({title: '提示', msg: '请求服务错误或当前网络不佳!', icon: 'warning', top: 200}); } }); } } }); } </script> <!-- JS for show/hide column--> <script> var showFlag = true function showAllCol() { if (showFlag) { $table.bootstrapTable('showColumn', 'category'); $table.bootstrapTable('showColumn', 'description'); $table.bootstrapTable('showColumn', 'full_name'); $table.bootstrapTable('showColumn', 'owner'); $table.bootstrapTable('showColumn', 'oecc_domestic'); $table.bootstrapTable('showColumn', 'oecc_oversea'); $table.bootstrapTable('showColumn', 'oe_domestic'); $table.bootstrapTable('showColumn', 'oe_oversea'); $table.bootstrapTable('showColumn', 'note'); $table.bootstrapTable('showColumn', 'tech_ss'); $table.bootstrapTable('showColumn', 'solution'); $table.bootstrapTable('showColumn', 'complexity'); $table.bootstrapTable('showColumn', 'tech_comment'); $table.bootstrapTable('showColumn', 'mkt_decision'); $table.bootstrapTable('showColumn', 'mkt_priority'); $table.bootstrapTable('showColumn', 'mkt_comment'); $table.bootstrapTable('showColumn', 'plan'); $table.bootstrapTable('showColumn', 'exe_owner'); $table.bootstrapTable('showColumn', 'exe_owner_mail'); $table.bootstrapTable('showColumn', 'exe_leader_mail'); $table.bootstrapTable('showColumn', 'cr_number'); $table.bootstrapTable('showColumn', 'cn_number'); $table.bootstrapTable('showColumn', 'attachments'); showFlag = false } else { $table.bootstrapTable('hideColumn', 'description'); $table.bootstrapTable('hideColumn', 'owner'); $table.bootstrapTable('hideColumn', 'oecc_domestic'); $table.bootstrapTable('hideColumn', 'oecc_oversea'); $table.bootstrapTable('hideColumn', 'oe_domestic'); $table.bootstrapTable('hideColumn', 'oe_oversea'); $table.bootstrapTable('hideColumn', 'note'); $table.bootstrapTable('hideColumn', 'solution'); $table.bootstrapTable('hideColumn', 'complexity'); $table.bootstrapTable('hideColumn', 'mkt_decision'); $table.bootstrapTable('hideColumn', 'mkt_priority'); $table.bootstrapTable('hideColumn', 'plan'); $table.bootstrapTable('hideColumn', 'exe_owner'); $table.bootstrapTable('hideColumn', 'exe_owner_mail'); $table.bootstrapTable('hideColumn', 'exe_leader_mail'); $table.bootstrapTable('hideColumn', 'cr_number'); $table.bootstrapTable('hideColumn', 'cn_number'); $table.bootstrapTable('hideColumn', 'attachments'); showFlag = true } } </script> {% endblock %}

2.1.3 Django后端

APIView使用了DRF框架,django内置的是View
查询功能可根据自己的需求更改

模型表models.py

class feature_ext(BaseModel):
    # properties for applicant
    title = models.CharField(max_length=200, verbose_name='主题', blank=False)
    owner = models.CharField(max_length=50,
                             blank=True,
                             verbose_name='申请人ID')
    full_name = models.CharField(max_length=50,
                                 blank=False,
                                 verbose_name='申请人')
    category = models.CharField(max_length=10,
                                blank=False,
                                choices=[('', '请选择'), ('NEW', '新需求'), ('NONSTD', '非标转标准化')],
                                verbose_name='类别')
    description = models.TextField(blank=False, verbose_name='描述')

    oecc_domestic = models.ManyToManyField(OeccDomestic, blank=True, verbose_name="OCL国内产品:")
    oecc_oversea = models.ManyToManyField(OeccOversea, blank=True, verbose_name="OCL海外产品:")
    oe_domestic = models.ManyToManyField(OeDomestic, blank=True, verbose_name="OE国内产品:")
    oe_oversea = models.ManyToManyField(OeOversea, blank=True, verbose_name="OE海外产品:")
    note = models.TextField(blank=True, verbose_name='备注')

    # properties for evaluator
    # Technical Review 技术团队评估
    tech_ss = models.ManyToManyField(subsystem, blank=True, verbose_name="受影响子系统:")
    solution = models.CharField(max_length=10,
                                blank=True,
                                choices=[('', '请选择'), ('Y', '有'), ('N', '无')],
                                verbose_name='技术可行性-成熟的技术方案(有/无)')
    complexity = models.CharField(max_length=10,
                                  blank=True,
                                  choices=[('', '请选择'), ('H', '高'), ('M', '中'), ('L', '低')],
                                  verbose_name='复杂度')
    tech_comment = models.TextField(blank=True, verbose_name='技术团队建议')

    # Marketing Review 产品管理团队评估
    mkt_decision = models.CharField(max_length=10,
                                    blank=True,
                                    choices=[('', '请选择'), ('GO', '同意'), ('GO_A', '同意并有行动项'),
                                             ('MEETING', '会议讨论'),
                                             ('NO', '拒绝')],
                                    verbose_name='市场部决策')
    mkt_priority = models.CharField(max_length=10,
                                    blank=True,
                                    choices=[('', '请选择'), ('H', '高'), ('M', '中'), ('L', '低')],
                                    verbose_name='优先级')
    mkt_comment = models.TextField(blank=True, verbose_name='市场团队建议')

    # Conclusion 结论
    # final_decision = models.TextField(blank=True, verbose_name='决策及产品管理团队建议')

    # Executor 执行方
    plan = models.DateField(null=True, blank=True, verbose_name='计划发布时间')
    exe_owner = models.CharField(max_length=50,
                                 blank=True,
                                 verbose_name='项目负责人')
    exe_owner_mail = models.EmailField(max_length=100,
                                       blank=True,
                                       verbose_name='邮箱')
    exe_leader_mail = models.EmailField(max_length=100,
                                        blank=True,
                                        verbose_name='经理邮箱')
    cr_number = models.CharField(max_length=200,
                                 blank=True,
                                 verbose_name='CR')
    cn_number = models.CharField(max_length=200,
                                 blank=True,
                                 verbose_name='CN')
    mrd_date = models.DateField(null=True, blank=True, verbose_name='MRD')
    exe_comment = models.CharField(max_length=1000,
                                   blank=True,
                                   null=True,
                                   verbose_name='备注')

    invalid_prd = models.CharField(max_length=500,
                                   blank=True,
                                   null=True,
                                   verbose_name='Invalid Products')
    # 添加user, file外键
    user = models.ForeignKey(User, null=True, blank=True, on_delete=models.SET_NULL)
    attachments = models.ManyToManyField(FeatureExtensionFile, blank=True)
    status = models.CharField(max_length=100,
                              blank=True,
                              null=True,
                              choices=[('0', '新需求'), ('1', '技术评估'), ('2', '市场评估'), ('3', '评估结论'), ('4', '实施计划')],
                              verbose_name='状态')

    class Meta:
        ordering = ['-id']

    def __str__(self):
        return self.title

序列化器serializer.py

class OeccDomesticSerializer(ModelSerializer):
    class Meta:
        model = OeccDomestic
        fields = '__all__'


class OeccDomesticField(serializers.PrimaryKeyRelatedField):
    def to_representation(self, value):
        if not value:
            return None
        obj = OeccDomestic.objects.get(pk=value.pk)
        if obj:
            data = OeccDomesticSerializer(obj).data
            return data


class OeccOverseaSerializer(ModelSerializer):
    class Meta:
        model = OeccOversea
        fields = '__all__'


class OeccOverseaField(serializers.PrimaryKeyRelatedField):
    def to_representation(self, value):
        if not value:
            return None
        obj = OeccOversea.objects.get(pk=value.pk)
        if obj:
            data = OeccOverseaSerializer(obj).data
            return data


class OeDomesticSerializer(ModelSerializer):
    class Meta:
        model = OeDomestic
        fields = '__all__'


class OeDomesticField(serializers.PrimaryKeyRelatedField):
    def to_representation(self, value):
        if not value:
            return None
        obj = OeDomestic.objects.get(pk=value.pk)
        if obj:
            data = OeccOverseaSerializer(obj).data
            return data


class OeOverseaSerializer(ModelSerializer):
    class Meta:
        model = OeOversea
        fields = '__all__'


class OeOverseaField(serializers.PrimaryKeyRelatedField):
    def to_representation(self, value):
        if not value:
            return None
        obj = OeOversea.objects.get(pk=value.pk)
        if obj:
            data = OeOverseaSerializer(obj).data
            return data

class FeatureExtensionQuerySerializer(ModelSerializer):
    category = serializers.SerializerMethodField()
    solution = serializers.SerializerMethodField()
    complexity = serializers.SerializerMethodField()
    mkt_decision = serializers.SerializerMethodField()
    mkt_priority = serializers.SerializerMethodField()
    status = serializers.SerializerMethodField()

 	# 多对多字段序列化
    oecc_domestic = OeccDomesticField(queryset=OeccDomestic.objects.all(), many=True)
    oecc_oversea = OeccOverseaField(queryset=OeccOversea.objects.all(), many=True)
    oe_domestic = OeDomesticField(queryset=OeDomestic.objects.all(), many=True)
    oe_oversea = OeOverseaField(queryset=OeOversea.objects.all(), many=True)
    tech_ss = TechSsFiled(queryset=subsystem.objects.all(), many=True)
    attachments = FeatureExtensionFileField(queryset=FeatureExtensionFile.objects.all(), many=True)
    # 一对多字段序列化
    user = UserField(queryset=User.objects.all())
    

    class Meta:
        model = feature_ext
        fields = '__all__'

	# 此处使用钩子函数是为了显示models中的元组可选字段,必须以get开头
    def get_category(self, obj):
        return obj.get_category_display()

    def get_solution(self, obj):
        return obj.get_solution_display()

    def get_complexity(self, obj):
        return obj.get_complexity_display()

    def get_mkt_decision(self, obj):
        return obj.get_mkt_decision_display()

    def get_mkt_priority(self, obj):
        return obj.get_mkt_priority_display()

    def get_status(self, obj):
        return obj.get_status_display()

视图函数views.py

class FeatureExtensionListView(APIView):
    def get(self, request):
        pageSize = int(request.GET.get('pageSize', 10))
        pageNumber = int(request.GET.get('pageNumber', 1))
        search_kw = request.GET.get('search_kw', '')
        sortName = request.GET.get('sortName', '')
        sortOrder = request.GET.get('sortOrder', '')

        obj_all = feature_ext.objects.all()
        # 查询
        if search_kw:
            obj_all = obj_all.filter(Q(title__icontains=search_kw) | Q(full_name__icontains=search_kw) |
                                     Q(tech_comment__icontains=search_kw) | Q(mkt_comment__icontains=search_kw))
        if sortName == 'no':
            sortName = 'id'
        # 方法一:直接先排序,再获取分页数据
        # if sortOrder == 'desc':
        #     page_obj_list = obj_all.order_by('-{}'.format(sortName))[(pageNumber - 1) * pageSize:(pageNumber) * pageSize]
        # else:
        #     page_obj_list = obj_all.order_by(sortName)[(pageNumber - 1) * pageSize:(pageNumber) * pageSize]

        # 方法二:django内置分页工具类
        # 1.先排序
        if sortOrder == 'desc':
            obj_list = obj_all.order_by('-{}'.format(sortName))
        else:
            obj_list = obj_all.order_by(sortName)
        paginator = Paginator(obj_list, per_page=pageSize)
        # 2.再获取指定页码的数据
        page_obj_list = paginator.page(pageNumber)

        total = obj_all.count()
        rows = FeatureExtensionQuerySerializer(page_obj_list, many=True).data
        page_data = get_page_all_data(total, rows, sortOrder, pageNumber, pageSize)
        # print(page_data)
        if page_data:
            return JsonResponse(page_data)
        return api_bad_request('数据加载失败!')
        
def get_page_all_data(total, rows, sortOrder, pageNumber, pageSize):
    for i in range(len(rows)):
        if sortOrder == 'desc':
            no = total - (pageNumber - 1) * pageSize - i
        else:
            no = (pageNumber - 1) * pageSize + i + 1
        rows[i]['no'] = no
    data = {"total": total, "rows": rows}
    return data

免责声明:以上内容和代码仅供参考!

你可能感兴趣的:(python,Django,前端,bootstrap,django,前端)