# 表格和 Admin

simplepro table 基于 elementui table,设置主要来自 ModelAdmin,写法与原生 admin 一致,但是在原生的基础上增加了和减少了部分字段。注意目前 table 仅支持下列这些字段,但是在编辑和添加页还有用到其他字段,请参考原生 admin 与 simpleui,simplepro 是完全基于 simpleui 的。

# 自定义按钮

admin 中的自定义 actions 也是支持的,也就是 simpleui 说说的自定义按钮。

定义方法和使用均与原生 admin 一致,不过 simpleui 在这基础上进行了扩展。可以参考自定义按钮文档

# Admin 字段

字段 类型 说明
list_display tuple table 显示的字段
search_fields tuple 搜索框搜索的字段
list_per_page int 每页显示的数量
list_filter array 筛选字段
list_display_links 显示连接进入编辑页的字段
fields_options dict 表格的表头字段设置
actions_show boolean 显示隐藏 action,默认为 True,只有显式指定为 False 的时候才隐藏
actions array 自定义按钮
native_render boolean 使用原生页面渲染,默认为Flase
list_filter_multiples array 3.1版本起可用,搜索下拉框多选字段,比如要在list_filter中包含才生效
top_html str 列表顶部显示的 html,支持 vue 组件和 element 组件,3.1.3+ 可用
bottom_html str 列表底部显示的 html,支持 vue 组件和 element 组件,3.1.3+ 可用

# top_html

在列表顶部显示的 html,支持 vue 组件和 element 组件,3.1.3+ 可用

# 例子

@admin.register(ProductCategory)
class ProductCategoryAdmin(admin.ModelAdmin):
    # 显示在列表顶部的一些自定义html,可以是vue组件,会被vue渲染
    top_html = ' <el-alert title="这是顶部的" type="success"></el-alert>'

    # 也可以是方法的形式来返回html
    def get_top_html(self, request):
        return self.top_html
1
2
3
4
5
6
7
8

# 效果

# bottom_html

在列表底部显示的 html,支持 vue 组件和 element 组件,3.1.3+ 可用

# 例子

@admin.register(ProductCategory)
class ProductCategoryAdmin(admin.ModelAdmin):
    # 显示在列表顶部的一些自定义html,可以是vue组件,会被vue渲染
    bottom_html = ' <el-alert title="这是底部的" type="success"></el-alert>'

    # 也可以是方法的形式来返回html
    def get_bottom_html(self, request):
        return self.top_html
1
2
3
4
5
6
7
8

# 效果

  • 字段互斥

    list_display_links 字段与 formatter 方法互斥

如果有 formatter 方法,list_display_links 中配置的字段将无任何作用。

# fields_options 字段

admin 中字段设置,及时 list_display 未定义该字段,在这里设置了也不会出错 表头字段完全遵循 elementui 的 table 文档:

https://element.eleme.cn/#/zh-CN/component/table (opens new window)

fields_options 支持自定义字段的值,比如 model 中的自定义方法 就算自定义字段

# 属性

目前支持以下属性

字段 类型 说明
fixed str 固定列,取值 left 和 right
sortable boolean 排序字段,默认为'custom'
width str 宽度,取值例如 100px
min_width str 最小宽度,取值例如 100px
resizable boolean 列是否可以调整宽度
class_name str 列的 className
label_class_name str 当前列标题的自定义类名
  • sortable 字段

排序字段,默认为'custom',取值为: true, false, 'custom'

其中为 custom 的时候网络排序

取值为 true,本地排序

自定义字段该值始终为 false 不排序

# fields_options 例子

fields_options = {
        'id': {
            'fixed': 'left',
            'width': '80px',
            'align': 'center'
        },
        'create_time': {
            'fixed': 'right',
            'width': '200px',
            'align': 'left'
        }
    }
1
2
3
4
5
6
7
8
9
10
11
12

# list_filter_multiples

下拉框多选字段,比如要在list_filter中包含才生效

# 示例


@admin.register(FilterMultiple)
class FilterMultipleAdmin(admin.ModelAdmin):
    """
    搜索框多选
    """

    list_display = ('pk', 'name', 'category')

    # list_filter要和list_filter_multiples匹配使用才有效果
    list_filter = ('category',)
    list_filter_multiples = ('category',)

1
2
3
4
5
6
7
8
9
10
11
12
13

# 效果

# 方法

字段 类型 说明
delete_queryset function 删除时触发该方法
formatter function 数据格式化
get_queryset function 获取自定义的 queryset
get_list_display function 获取自定义的 list_display
get_list_filter function 获取自定义的 list_filter
get_actions function 获取自定义的 actions
get_summaries function 获取底部统计数据
get_results function 获取返回的结果,1.2+版本生效
get_top_html function 列表顶部显示的 html,支持 vue 组件和 element 组件,3.1.3+ 可用
get_bottom_html function 列表底部显示的 html,支持 vue 组件和 element 组件,3.1.3+ 可用

# formatter 方法

  • 入参
字段 类型 说明
obj object 当前对象
field_name str 字段名
value object 字段值
  • 返回

返回参数为单元格显示的值,可以是 html,可以是文本。

# formatter 例子

def formatter(self, obj, field_name, value):
    # 这里可以对value的值进行判断,比如日期格式化等
    return value
1
2
3

# delete_queryset 说明

例子:

def delete_queryset(self, request, queryset):
    #这里可以做些自定义的处理
    pass
1
2
3
  • 返回

如果返回的是 queryset,那么程序将会调用 delete 方法执行删除。如果返回的是 None,将不会做任何动作

  • 从 3.0 版本开始

如果想要自己处理删除逻辑,不需要 simplepro 直接删除数据,可以将delete_queryset方法返回True 这样 simplepro 就不会执行删除动作。可以自己实现一些逻辑删除

例如:

def delete_queryset(self,request,queryset):
    queryset.filter(xxxx...).update(is_delete=False)
    return True
1
2
3

# get_queryset 说明

例子:

 def get_queryset(self, request):
        qs = super().get_queryset(request)

        return qs.filter(id__gte=1)
1
2
3
4

注意,get_queryset 可以返回为 None,包括 pass 也是返回为 None。如果为 None,的时候 该 queryset 将会被丢弃,框架将会从 model 中获取 queryset

qs=model.objects.get_querset()
1

可以利用这个方法来控制自定义的数据权限,该方法与原生 admin 一致。

# get_list_display 说明

    def get_list_display(self, request):
        # 这里可以进行判断,动态返回某些字段或表头
        return self.list_display
1
2
3

# get_list_filter 说明

    def get_list_filter(self, request):
        # 这里可以进行判断,动态返回list_filter
        return self.list_filter
1
2
3

# get_actions 说明

    def get_actions(self, request):
        # 这里可以进行判断,动态返回actions
        actions = super(EmployeAdmin, self).get_actions(request)
    return actions
1
2
3
4

# get_summaries 说明

在 modeladmin 中加入该方法后,会自动在表格底部增加一列合计列。 可以用 request 来控制动态显示,也可以直接使用带有搜索条件的 queryset,该 queryset 是列表数据的深拷贝对象,不带排序和分页。

Demo1.

    # 动态统计,Simple Pro独有功能
    def get_summaries(self, request, queryset):
        # 自定义统计,可以根据request的页面 来统计当前页的数据,queryset 为深拷贝对象,如果传入的话 可能会影响列表的数据
        # 返回的数据 为数组,对应列表的每一列
        # 不支持html

        # 如果想根据人员权限来动态展示,可以直接返回不同的数组,或者返回为None,为None的时候,不显示统计列

        # 如果想统计满足当前搜索条件的数据的话 ,可以直接使用queryset.来进行统计
        if request.POST.get('current_page') == '2':
            return None
        else:
            # 需要有空字符串占位
            return ('合计', '321', '1213123', '123123', '', '', '', '测试')
1
2
3
4
5
6
7
8
9
10
11
12
13
14

Demo2.

    # 动态统计,Simple Pro独有功能
    def get_summaries(self, request, queryset):
        # 如果想统计满足当前搜索条件的数据的话 ,可以直接使用queryset.来进行统计
        # queryset.aggregate(total=Sum('money')).get('total')

        a = "¥{}".format(Record.objects.aggregate(total=Sum('money')).get('total'))
        print(a)
        # 需要有空字符串占位
        return ('', '数据合计', '', '', a, '2020年01月14日')
1
2
3
4
5
6
7
8
9

界面效果:

# get_results 获取返回结果

该方法在 simplepro 1.2 及以上版本中生效,用于处理最终的结果集。

例子:


    # 注意:
    # 这里的queryset 改变过滤条件将不会影响返回的结果。如果需要操作queryset,
    # 请在get_queryset方法中进行
    # results 将会是一个 dict list,而不是对象,获取属性 需要用get

    def get_results(self, results, request, queryset):
        print('处理结果集')
        new_results=[]

        for item in results:
            if 'aa' in item:
                print(item.get('aa'))
                item['aa']='这是一个测试属性'

            new_results.append(item)

        return new_results
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# Media 自定义引入 js 和 css

Media 遵从原生 django admin 的写法,并且处理也是 django 实现,simplepro 未做任何文件处理,只做引入动作。

# 例子


@admin.register(Department)
class DepartmentAdmin(admin.ModelAdmin):

    class Media:
        js=('aa.js','bb.js')
        css=('dd.css','cc.css')

1
2
3
4
5
6
7
8

在页面解析的时候 会调用下列方式进行引入

<script type="text/javascript" src="{% static 'aa.js'%}">
1

# 核心源码

  • 引入 js 部分:
{% if media.js %} {% for js in media.js %}
<script type="text/javascript" src="{% static js %}"></script>
{% endfor %} {% endif %}
1
2
3
  • 引入 css 部分:
{% if media.css %} {% for css in media.css %}
<link rel="stylesheet" href="{% static css %}" />
{% endfor %} {% endif %}
1
2
3

在通过引入自己的 js 和 css 之后,可以对页面进行扩展,调用 simplepro 的 js sdk 可以实现意想不到的效果,比如表格 format,添加自定义按钮,拦截按钮事件等。具体请看 jssdk

# 常见问题

# 1. 权限

增删改查按钮,可以利用系统自带的权限进行控制,对于自定义的 action,也支持权限控制。 请参考文档:权限文档

# 2. 数据权限

对于数据级别的权限,不属于框架的范畴,这是需要自己在业务逻辑的处理上进行控制,可以利用ModelAdmin中的get_queryset方法来进行数据的过滤。

例如:


class SimpleAdmin(...):

    def get_queryset(request,qs):
        qs.filter(user__id=123,type_id=321)
        return qs

1
2
3
4
5
6
7

# 自定义列

自从simplepro 4.0 及以上版本支持在自定义列中 返回Vue组件和Element-UI的组件。表格会动态渲染

示例:


@admin.register(Dialog)
class DialogAdmin(admin.ModelAdmin):
    list_display = ('custom_row_btn')

    def custom_row_btn(self, *args, **kwargs):
        # 从4.0开始 支持element-ui的组件
        return format_html(
            """
            <a href="javascript:;">查看详情</a>
            <el-button type="success" icon="el-icon-check" circle @click="$message('这是一条消息提示')"></el-button>
            <el-button type="danger" icon="el-icon-refresh" circle @click="app.refreshData()"></el-button>
            """)

   custom_row_btn.short_description = '支持组件'

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16