页面上展示数据表的表头

我们注册了UserInfo表之后,在视图函数change_list_view中执行data_list = self.model_class.objects.all()就可以拿到该表中的所有数据,但是页面上还欠缺一个表头信息,通过verbose_name = self.model_class._meta.get_field('name').verbose_name拿到字段对应的Field对象再拿到我们设置上去的verbose_name的值。
多个模型类下的字段是不相同的,所以要展示那些字段我们交给使用者来决定,在class UserInfoHandle(StarkHandle):类中给定页面中要展示的字段内容。
代码:

class StarkHandle(object):"""处理请求的视图函数所在的类,公共类"""display_list = []  # 定义默认的display_list,用户没有继承此类并重写这个值,将默认不会展示任何字段def __init__(self, model_class, prev):self.model_class = model_classself.prev = prevdef change_list_view(self, request):header_list = []for key in self.display_list:  # 根据继承的特性,用户继承StarkHandle类,重写display_list值,并且注册,此时self的对象就是用户自定义继承StarkHandlr的类,会访问用户定义的display_list值。verbose_name = self.model_class._meta.get_field(key).verbose_nameheader_list.append(verbose_name)print(header_list)data_list = self.model_class.objects.all()print(data_list)return render(request, 'stark/change_list.html', {'header_list': header_list})

change_list.html文件

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<table><thead><td>{% for header in header_list %}<th>{{ header }}</th>{% endfor %}</td></thead>
</table>
</body>
</html>

注册UserInfo表:

class UserInfoHandle(StarkHandle):display_list = ["name", "age", "mail", "depart"]site.register(UserInfo, UserInfoHandle)

效果:

减少UserInfoHandle中的display内容,展示的信息对应减少

class UserInfoHandle(StarkHandle):display_list = ["name", "age", "mail"]site.register(UserInfo, UserInfoHandle)


注册Depart表

class DepartHandle(StarkHandle):display_list = ['id', 'title']
site.register(Depart, DepartHandle)

数据表中数据的展示

通过数据库查找拿到的数据,不能直接在html中使用,因为我们在html中无法使用反射获取字段的数据,所以在后端要构造好数据再传递到html中使用。

代码

class StarkHandle(object):def change_list_view(self, request):header_list = []for key in self.display_list:verbose_name = self.model_class._meta.get_field(key).verbose_nameheader_list.append(verbose_name)data_list = self.model_class.objects.all()body_list = []  # 构造出给前端使用的数据结构,包含该表中那个的所有数据"""body_list = [['胡说', '17', 'hushuo@qq.com'],  # 数据表中的一行数据['呼哈', '32', 'huha@qq.com']]"""for item in data_list:# 构造一行数据row_list = []for key in self.display_list:row_list.append(getattr(item, key))  # 拿到每行数据的字段内容body_list.append(row_list)return render(request, 'stark/change_list.html', {'header_list': header_list, 'body_list': body_list})

change_list.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<table border="1"><thead><tr>{% for header in header_list %}<th>{{ header }}</th>{% endfor %}</tr></thead><tbody>{% for row in body_list %}<tr>{% for ele in row %}<td>{{ ele }}</td>{% endfor %}</tr>{% endfor %}</tbody>
</table>
</body>
</html>


用户可以通过自定义的类中修改display_list的内容来控制前端展示的字段内容,如不想展示年龄就可以设置为display_list = ["name", "mail"]

列表页面的默认展示

此时我们代码逻辑是,用户必须继承StarkHandle类,并在自定义类下按照表中想展示的字段的值给dislpay_list设置值。我们有些时候就不想重写这个类,就直接使用StarkHandle,就需要添加默认的显示。

默认显示的思路是:表头是当前表的表名,每一行展示的是该表对应模型类的对象。

代码:

class StarkHandle(object):def change_list_view(self, request):header_list = []if self.display_list:for key in self.display_list:verbose_name = self.model_class._meta.get_field(key).verbose_nameheader_list.append(verbose_name)else:# 用户没有继承这个类和重新给display_list赋值,使用当前类中的display_list# 表头信息为该表名称header_list.append(self.model_class._meta.model_name)data_list = self.model_class.objects.all()body_list = []  # 构造出给前端使用的数据结构,包含该表中那个的所有数据for item in data_list:# 构造一行数据row_list = []if self.display_list:for key in self.display_list:row_list.append(getattr(item, key))else:# 展示对象信息到页面row_list.append(item)body_list.append(row_list)return render(request, 'stark/change_list.html', {'header_list': header_list, 'body_list': body_list})

使用默认的StarkHandle类

from stark.service.v1 import site
site.register(Depart)

页面展示:

列表页面预留钩子方法(自定义扩展列显示)重要

继承了StarkHandle类后,可以定义display_list手动修改器值来决定列表页面显示哪些列的内容,如果要根据当前登录的用户来决定展示哪些列,此时代码就满足不了需求了。

思路:在父类中定义一个get_display_list方法,在后续使用到self.dislpay_list获取展示列的地方都修改为调用get_dislpay_list方法,用户动态自定义哪些用户展示哪些列时就可以在继承的子类中重写该方法,来动态的获取展示列的信息(根据继承特性)

代码:

class StarkHandle(object):"""处理请求的视图函数所在的类,公共类"""display_list = []def get_display_list(self):"""获取页面上应该显示的列,用户集成该类,可以做显示列的自定义扩展: 根据用户的不同显示不同的列:return:"""value = []  # 扩展的显示列的列表value.extend(self.display_list)  # 将原有的display_list添加到扩展列表中return value  # 返回的是 扩展列+用户在display_list中写死的默认展示列def change_list_view(self, request):header_list = []display_list = self.get_display_list()  # 通过get_display_list方法拿到要展示的数据,如果用户继承此类并重写了此方法就会调用子类中的该方法,达到扩展的目的if display_list:for key in display_list:verbose_name = self.model_class._meta.get_field(key).verbose_nameheader_list.append(verbose_name)else:# 用户没有继承这个类和重新给display_list赋值,使用当前类中的display_list# 表头信息为该表名称header_list.append(self.model_class._meta.model_name)data_list = self.model_class.objects.all()body_list = []  # 构造出给前端使用的数据结构,包含该表中那个的所有数据for item in data_list:# 构造一行数据row_list = []if display_list:for key in display_list:row_list.append(getattr(item, key))else:# 展示对象信息到页面row_list.append(item)body_list.append(row_list)return render(request, 'stark/change_list.html', {'header_list': header_list, 'body_list': body_list})

使用:

class UserInfoHandle(StarkHandle):display_list = ["name", "age", "mail"]  # 不重写get_display_list方法时,默认展示的列def get_display_list(self):# 动态返回要展示的列return ['name', 'mail']site.register(UserInfo, UserInfoHandle)

页面展示:

列表页面自定义函数扩展

在列表页面不仅也可显示数据库表的信息,还可以添加新的一列数据,数据内容由用户来决定,如在每行数据后添加删除的按钮。

新的一列内容是由用户定义的,设计思路是,用户定义一个函数,将函数添加到display_list中,在遍历display_list时,是字符串在数据库表中取值,是函数对象,拿到函数调用后的返回值作为页面内容的展示。用户将想显示的新一列的数据通过函数返回。

代码:

class StarkHandle(object):"""处理请求的视图函数所在的类,公共类"""display_list = []def __init__(self, model_class, prev):self.model_class = model_classself.prev = prevdef get_display_list(self):"""获取页面上应该显示的列,用户集成该类,可以做显示列的自定义扩展: 根据用户的不同显示不同的列:return:"""value = []value.extend(self.display_list)return valuedef change_list_view(self, request):header_list = []display_list = self.get_display_list()  # 通过get_display_list方法拿到要展示的数据,如果用户继承此类并重写了此方法就会调用子类中的该方法,达到扩展的目的if display_list:for key_or_func in display_list:if isinstance(key_or_func, FunctionType):# 是函数对象,调用该函数,将返回值作为表头内容verbose_name = key_or_func(self, is_header=True)else:verbose_name = self.model_class._meta.get_field(key_or_func).verbose_nameheader_list.append(verbose_name)else:# 用户没有继承这个类和重新给display_list赋值,使用当前类中的display_list# 表头信息为该表名称header_list.append(self.model_class._meta.model_name)data_list = self.model_class.objects.all()body_list = []  # 构造出给前端使用的数据结构,包含该表中那个的所有数据for item in data_list:# 构造一行数据row_list = []if display_list:for key_or_func in display_list:if isinstance(key_or_func, FunctionType):# 是函数对象,将函数调用返回值作为该行的一个值row_list.append(key_or_func(self, obj=item, is_header=False))else:row_list.append(getattr(item, key_or_func))else:# 展示对象信息到页面row_list.append(item)body_list.append(row_list)return render(request, 'stark/change_list.html', {'header_list': header_list, 'body_list': body_list})

继承StarkHandle类

class UserInfoHandle(StarkHandle):def display_edit(self, obj=None, is_header=None):"""自定义列表展示页的某一列数据,在列表页面展示除数据库表外的数据,如:编辑按钮:param obj: 要操作的模型类实例化对象,一个模型类实例化对象对应的是数据库中的一行数据:param is_header: 一列有表头和数据两种,用于判断是返回表格数据还是表头数据:return:"""if is_header:return "编辑表头"# return obj.name  # 返回想展示到页面的内容,用户自己定制return mark_safe('<a href="https://www.baidu.com">编辑</a>')display_list = ["name", "age", "mail", display_edit]

注册

site.register(UserInfo, UserInfoHandle)

页面展示:
新增的一列为编辑表头,用户可以通过自定义函数,并添加到display_list,根据函数的返回值来控制新增一列的内容

我们点击编辑会调转到百度页面,当然这只是一个测试效果,现在就把编辑的链接通过反向获取写入到a标签中。

1.后端的反向获取,先导入reverse函数from django.urls import reverse
2.我们在自动生成别名时,给设定了名称空间,其值在StarkSite类中定义

class StarkSite(object):def __init__(self):self._registry = []self.name = 'stark'self.namespace = 'stark'

3.在用户自定义的handle类中,我们要是用反向解析可以直接编写代码

class UserInfoHandle(StarkHandle):def display_edit(self, obj=None, is_header=None):if is_header:return "编辑表头"name = "{}:{}".format('stark', self.get_change_url_name)return mark_safe('<a href="{}">编辑</a>'.format(reverse(name, args=(obj.pk,))))display_list = ["name", "age", "mail", display_edit]

4.直接使用’stark’字符串,这种方式功能可以实现,但是是不可取的,当我们名称空间的值修改时,在用户自定义的handle类中‘stark’字符串都需要修改,不符合我们预期,我们希望的是只修改一处StarkSite类中的namesapce值,其他地方不需要改动。所以就要在用户自定义类中拿到StarkSite类中的元素,我们修改StarkSite的代码:

class StarkSite(object):def __init__(self):self._registry = []self.name = 'stark'self.namespace = 'stark'def register(self, model_class, handle_class=StarkHandle, prev=None):self._registry.append({'model_class': model_class, 'handle': handle_class(self, model_class, prev), 'prev': prev})

5.在用户注册时,将self传入到handle_class进行实例化对象,self就是StarkSite的实例化对象,在handle_class的类中修改代码:

class StarkHandle(object):def __init__(self, site, model_class, prev):self.site = site  # 每个自定义继承此类的类中,就能拿到namespace的值self.model_class = model_classself.prev = prev

6.用户自定义handle类中的反向解析:

class UserInfoHandle(StarkHandle):def display_edit(self, obj=None, is_header=None):if is_header:return "编辑表头"# return obj.namename = "{}:{}".format(self.site.namespace, self.get_change_url_name)return mark_safe('<a href="{}">编辑</a>'.format(reverse(name, args=(obj.pk,))))display_list = ["name", "age", "mail", display_edit]

点击编辑的页面展示:

列表页面内容补充

所有表的列表展示页面均添加修改和删除两列

现在有三张表:

  • app01

    • Depart
    • UserInfo
  • app02
    • Host

需要为这三张表自定义继承了StarkHandleDepartHandle,UserInfoHandle,HostHandle类,并在每个类下都添加相同的代码:

def display_edit(self, obj=None, is_header=None):"""自定义列表展示页的某一列数据,在列表页面展示除数据库表外的数据,如:编辑按钮:param obj: 要操作的模型类实例化对象,一个模型类实例化对象对应的是数据库中的一行数据:param is_header: 一列有表头和数据两种,用于判断是返回表格数据还是表头数据:return:"""if is_header:return "编辑表头"# return obj.namename = "{}:{}".format(self.site.namespace, self.get_change_url_name)return mark_safe('<a href="{}">编辑</a>'.format(reverse(name, args=(obj.pk,))))def display_del(self, obj=None, is_header=None):"""自定义列表展示页的某一列数据,在列表页面展示除数据库表外的数据,如:编辑按钮:param obj: 要操作的模型类实例化对象,一个模型类实例化对象对应的是数据库中的一行数据:param is_header: 一列有表头和数据两种,用于判断是返回表格数据还是表头数据:return:"""if is_header:return "删除表头"# return obj.namename = "{}:{}".format(self.site.namespace, self.get_delete_url_name)return mark_safe('<a href="{}">删除</a>'.format(reverse(name, args=(obj.pk,))))display_list = [display_edit, display_del]  # 在display中添加这两个函数对象

同样的代码我们需要写三份,有代码冗余,对于编辑和删除功能,应该是每个表都应有的,可以将这两个函数写到StarkHandle类中,在用户继承的类中只需要在display_list添加函数对象即可添加这两个功能

class UserInfoHandle(StarkHandle):display_list = ["name", "age", "mail", StarkHandle.display_edit, StarkHandle.display_del]class DepartHandle(StarkHandle):display_list = ['id', 'title', StarkHandle.display_edit, StarkHandle.display_del]site.register(UserInfo, UserInfoHandle)
site.register(Depart, DepartHandle)

表中choices字段的列表页展示

为UserInfo表添加性别字段:

class UserInfo(models.Model):name = models.CharField(verbose_name="用户名", max_length=32)age = models.CharField(verbose_name="年龄", max_length=32)gender_choices = ((1, '男'),(2, '女'),)gender = models.IntegerField(verbose_name="性别", choices=gender_choices, default=1)mail = models.CharField(verbose_name="邮箱", max_length=32)depart = models.ForeignKey(verbose_name="部门", to='Depart')def __str__(self):return self.name

我们用户表用的gender字段是choices类型,在数据库中存储的是数字1,2,当我们在进行列表页展示加入了gender字段时,现有的处理逻辑是去数据库中拿到该字段对应的值去展示,如果不经过特殊处理,在页面上只能显示出数字,不能展示该数字对应的字符串内容。

针对choices字段的特殊处理:
在模型类实例化对象中有get_字段名_display(),如果该字段是一个choices类型,就可以通过这个方法拿到对应的字符串内容。

我们最初的想法是在用户自定义的handle类中实现对于choices字段的特殊处理函数,再将函数对象放入display_list列表中进行展示

class UserInfoHandle(StarkHandle):def display_gender(self, obj=None, is_header=None):# 对gender字段显示的特殊处理函数if is_header:return '性别'return obj.get_gender_display()display_list = ["name", "age", display_gender, 'gender', "mail", StarkHandle.display_edit,StarkHandle.display_del]

此时页面显示的效果:性别成功的显示字符串内容

但是,如果这个表中有三个甚至更多个choices类型的字段,或者其他表中有choices类型字段,有几个这样子的字段,我们就需要添加几个这样子的函数

仔细分析下来,这多个特殊处理函数的内容有红框两处内容不同,其他代码都一致,这两个值是否可以动态改变呢,一个函数的参数是固定不变的,在不修改参数值得情况下,还需要往函数中传入其他的值,可以想到我们可以使用闭包来实现,代码就出来了,我们将代码写在公共的stark组件中,其他app下都可以使用到次函数。

def get_choice_text(title, field):"""对于stark组件中,自定义列时,choice字段如果想显示中文信息,调用此方法:param title: 希望页面显示得表头:param field: 字段名称:return:"""def inner(self, obj=None, is_header=None):if is_header:return titlemethod = "get_{}_display".format(field)return getattr(obj, method)()return inner

在用户自定义的handle类中,动态传入想要展示到页面的choices字段的表头,和字段名,字段名用来组合获取对于字符串的get_xxx_display方法。

from stark.service.v1 import site, StarkHandle, get_choice_text
class UserInfoHandle(StarkHandle):display_list = ["name", "age", get_choice_text('性别', 'gender'), "gender", "mail", StarkHandle.display_edit, StarkHandle.display_del]site.register(UserInfo, UserInfoHandle)

页面展示:

不管有多少个choices类型的字段,直接在display列表中添加get_choice_text('表头展示的内容', '模型类对应choices的字段名称'),来进行展示。

列表展示页面应用样式

应用之前rbac中开发的layout.html模板样式

{% extends 'layout.html' %}
{% block content %}
<div class="luffy-container"><table border="1" class="table table-bordered"><thead><tr>{% for header in header_list %}<th>{{ header }}</th>{% endfor %}</tr></thead><tbody>{% for row in body_list %}<tr>{% for ele in row %}<td>{{ ele }}</td>{% endfor %}</tr>{% endfor %}</tbody></table>
</div>
{% endblock %}


页面应用样式代码链接:https://download.csdn.net/download/no_name_sky/21130443

CRM项目之stark组件url的视图函数和列表页面基本展示2相关推荐

  1. CRM项目之stark组件之列表展示页面详细功能实现3

    分页 分页器组件代码 """ 分页组件 """class Pagination(object):def __init__(self, cur ...

  2. CRM项目之stark组件之列表页面功能补充4

    排序 用户可以在自定义的handle类中来决定排序的规则 StarkHandel类中编写如下代码,给用户留出接口 class StarkHandle(object):order_list = [] # ...

  3. Django 3.2.5博客开发教程:URL与视图函数

    在讲URL与视图函数之前我们先给大家简单介绍一下用户访问网站的流程.我们访问一个网站的时候,一般先打开浏览器,然后在浏览器的地址栏里输入一个网址,也就是URL,然后回车,我们就可以在浏览器里看到这个网 ...

  4. flask第七篇——URL与视图函数的映射

    有兴趣的朋友可以添加微信公众号:自动化测试实战 今天开始就要进入正题了.大家都准备好了吧~ 代码提示 先和大家说个小知识点:有同学后台说输入flask代码pycharm不提示,现在告诉你一个解决方法: ...

  5. Django之url和视图函数

    URL-统一资源定位符(Uniform Resource Locator)用来表示互联网某个资源的地址,类比理解为windows下某个文件的路径.URL的一般语法格式为(注:[]代表其中的内容可省略) ...

  6. Python框架篇之Django(路由系统URL、视图函数views)

    文章目录 一.路由系统(URL) 二.视图函数(views) 一.路由系统(URL) 1.URL配置 (URLconf)就像Django 所支撑网站的目录.它的本质是URL模式以及要为该URL模式调用 ...

  7. 菜谱项目(个人中心、首页index、菜谱列表页面)

    一.个人中心 1.选项卡操作 功能分析: 1.点击切换选项上边样式 active ===>activeIndex下边内容 控制显示隐藏 hidden ===>acitveIndex 代码案 ...

  8. Stark 组件:快速开发神器 —— 页面显示

    说道 Stark 你是不是不会想到他--Tony Stark,超级英雄钢铁侠,这也是我的偶像. 不过我们今天要开发的 Stark 组件,倒是跟他的人工智能助手 JARVIS 有些类似,是帮助我们快速开 ...

  9. 动力节点CRM项目开发【准备篇】

    CRM项目开发[准备篇] (参考B站视频CRM项目) 01-基本技术框架 视图层(View):展示数据,负责跟用户交互 html,css,js,jquery,bootstrap 控制层(Control ...

最新文章

  1. 玩皮,DIY了一个本子
  2. 二丶Linux安装xdd-plus教程及必备依赖的安装+青龙对接xdd
  3. python编写自动化脚本 与shell_脚本安装Discuz论坛(shell + Python 实现自动化安装)...
  4. 线性一致性与全序广播------《Designing Data-Intensive Applications》读书笔记12
  5. Mybatis工作流程及其原理与解析
  6. 7-1 输出全排列 (20 分)(全排列+递归+图解)Come Baby
  7. 双机之间的串行通信设计 c语言编程,双机串行通信设计精品.doc-资源下载人人文库网...
  8. 玩转 SpringBoot 2 快速整合 | 丝袜哥(Swagger)
  9. C语言学习笔记---字符串转换函数
  10. Eclipse中,lombok安装
  11. Attempt to do update or delete on table educator.t_item_info that does not use an AcidOutputFormat o
  12. JAVA并发编程实践 下载
  13. JVM——字节码指令(转)
  14. ajax php投票记录功能,PHP 实例 AJAX 投票 | 菜鸟教程
  15. Gcd HYSBZ - 2818
  16. MinGW32编译ffmpeg+libsrt
  17. 阿里云ACA、ACP和ACE认证考试有什么区别?考生应该如何选择?-阿里云开发者社区
  18. 3dmaxobj导出选项_3DMAX怎么导出obj?
  19. java正则中REGEX = [\u4e00-\u9fa5]+是什么意思
  20. 老照片修复-上色-生成动图的操作方法

热门文章

  1. php香港主机,PHP香港主机选购指南
  2. Linux运维发展如何?哪家培训机构质量高?
  3. Webshell工具的流量特征分析(菜刀,蚁剑,冰蝎,哥斯拉)
  4. 英语单词学习-17-112
  5. 你有多享受孤独,你就配有多自由
  6. Skynet服务器框架(三) Mac OS X环境安装
  7. ios图片编辑(看这个就够了!)
  8. 台湾股坛教父:漂亮50还能够走多远
  9. ygo游戏王卡组_游戏王卡组教程系列【光道卡组】
  10. 计算机考研|跨考计算机的同学不妨看看这篇文章