当前位置: 首页 > news >正文

Flask+LayUI开发手记(十一):选项集合的数据库扩展类

        条目较少的选项集合,确实可以在程序中直接定义(其实最合适的还是存储在一个分类别的数据库表里),但条目较多的选项集合,或者是复杂的树型结构选项集合,一般都是存储在数据库中的,这样维护起来比较方便,也容易迁移和共享。所以,在完成基础选项集合框架后,考虑应用的方便性,面向数据库存储的选项集合扩展类就成了下一步开发的任务。

        有了基础类做底,这些实现扩展起来也是十分方便。基于数据库存储的类包括两大类型,一种是列表类,这个就是基础选项类的扩展,数据结构没有区别,只是多了选项条目从数据库中装载到内存中的过程,另一种是树型类,它的数据结构比列表类复杂了一些,数据库里也是以父子ID方式存放数据,放在内存里则是一个包括父子ID和名称的字典,依据父子ID关系可以生成与layui-tree组件接口一致的树型结构传送到前端。

        下面这段是列表类的python服务类List_OptionSet,它是基于OptionSet基础类扩展的,所以,相同功能的类函数直接复用基础类。重写的子类函数包括构造函数__init__()和get_dict(),新写的函数包括load()和reload()。可以看出,列表类与基础类的区别是比较小的。

 (注:写到这儿时,发现原来的基础类中有个错误,就是reload()函数也必须在基础类里编写出来,否则如果对基础类选项集合进行重载时,就会出现系统级错误)

#取自数据库表的列表选项集合
class List_OptionSet(OptionSet):def __init__(self,dbclass=None,fdinf=None,n_opt=None,t_opt=None) :super().__init__()self.dbclass = dbclassself.fdinf = fdinfself.opt_name = n_optself.opt_title = t_optif n_opt :sysOptionPool.add_optset(n_opt,self)# 取选项字典def get_dict(self):if (self.opt_dict == None):if self.load(self.dbclass,self.fdinf) == 0:return Nonereturn self.opt_dict# 数据装入函数def load(self,dbclass,fdinf):logging.info('Load Table OptionSet %s....' % self.opt_name)fdkey = fdinf.get('key')fdname = fdinf.get('name')filtstr = fdinf.get('filter')try :rows = db.session.query(dbclass).filter(text(filtstr)).all()opt_info = {}for irow in rows:valkey = getattr(irow,fdkey)valname = getattr(irow,fdname)opt_info[valkey] = valnameself.opt_dict = opt_infoexcept SQLAlchemyError as e:logging.debug('装入选项集合[%s]数据库读取失败!!%s' % (self.opt_name,str(e.orig)))return 0return 1#数据重载函数def reload(self) :rtncode = self.load(self.dbclass,self.fdinf)if rtncode == 0 :return 0if self.opt_name :sysOptionPool.add_optset(self.opt_name,self)return 1

        列表类实现时,重点要强调一下,类实例初始化时并不会从数据库中取数据,而是在第一次使用时,如果判断条目字典为空,才会从数据库中加载条目数据,这是系统中经常用到的方法,因为在系统启动时,所有的选项实例就已经生成了,但大部分的实例在运行时并不会用到,如果这时加载,那会占用较多内存,并且启动时间也会加长。

        上面这个实现在get_dict()中完成,当self.opt_dict为空时调用load函数完成加载。reload()函数的主要用途是将条目数据从数据库重新装载到类实例中。当选项条目被维护后,就会调用此函数完成选项集合的同步。重载是选项集合服务一个路由请求实现,在上一节中有体现。

        下面这段代码是树型选项集合类Tree_OptionSet的实现,它是在列表类的基础上扩展的。可以看出,树型类进行了大量的扩充,几乎所有的函数都进行了重写,并且增加了多个函数。树型选项的存储结构不再是简单的键值对字典,而是一个以ID为键字的复合字典,并为前端提供了列表、映射以及树型等多种格式的数据服务。

##树型的选项集合类    
class Tree_OptionSet(List_OptionSet) :def __init__(self,dbclass=None,fdinf=None,n_opt=None,t_opt=None) :super().__init__()self.dbclass = dbclassself.fdinf = fdinfself.opt_name = n_optself.opt_title = t_optif n_opt :sysOptionPool.add_optset(n_opt,self)# 获取选项名称def get_name(self,id) :dt_id = self.get_dict().get(id)if dt_id == None :return '-'return dt_id.get('name')# 获取选项格式串(废弃保留)def id_format(self,id):dt_id = self.get_dict().get(id)if dt_id == None :return '-'idname = dt_id.get('name')if isinstance(id, str) :return id + '_' + idnameelse :return str(id) + '_' + idname# 获取选项映射def get_map(self):itemlist = {}d_opt = self.get_dict()if (d_opt == None) :return Nonefor (k,v) in d_opt.items():itemlist[k] = v['name']return itemlist# 获取选项列表def get_list(self,**kwargs) :itemlist = []d_opt = self.get_dict()if (d_opt == None) :return Nonefor (k,v) in d_opt.items():item = [k,v['name'],v['pid'],0]itemlist.append(item)f_sort = kwargs.get('sort')if f_sort == None or f_sort == False:return itemlistreturn sorted(itemlist)# 数据装载def load(self,dbclass,fdinf):logging.debug('Load Table Tree Options %s....' % self.opt_name)fdkey = fdinf.get('key')fdname = fdinf.get('name')fdvalue = fdinf.get('value')fdparent = fdinf.get('parent')filtstr = fdinf.get('filter')try :rows = db.session.query(dbclass).filter(text(filtstr)).all()opt_info = {}for irow in rows:valkey = getattr(irow,fdkey)valname = getattr(irow,fdname)valparent = getattr(irow,fdparent)opt_info[valkey] = dict(name=valname,pid=valparent)if (fdvalue != None) :valvalue = getattr(irow,fdvalue)opt_info[valkey]['value'] = valvalueself.opt_dict = opt_infoexcept SQLAlchemyError as e:logging.debug('装入树型选项集合[%s]数据库读取失败!!%s' % (self.opt_name,str(e.orig)))return 0return 1# 获取选项集合def get_option(self,optcat=None) :return self.get_tree()# 获取选项树型def get_tree(self) :item_opt = self.get_list(sort=True)if item_opt == None:return Noneif hasattr(self,'fdinf') :root_id = self.fdinf.get('rootid')else :root_id = 0#logging.debug('item_opt: %s' % item_opt)item_tree = self.build_tree(item_opt,root_id,0)return item_tree# 生成选项树型# 基于Layui-Tree接口格式生成数据def build_tree(self,data,p_id,level=0):tree = []for item in data:if item[2] !=p_id:continuerow = dict(id = item[0], title= item[1], parent_id=item[2],level= level)if level==0:row['spread'] = Truechild = self.build_tree(data, row['id'], level+1)row['children'] = []if child:row['children'] += childtree.append(row)return tree

        通过加载函数load()完成条目字典的原始数据结构加载,其数据结构为{id111:{name:xxx,pid:xxx,value:xxx},id222:{...},...}。之后由原始数据结构为基础,然后通过一系列函数完成数据服务,主要包括:

get_name():根据键值取名称

id_format():生成格式化的选项展示(后台生成展示项时用)

get_map():生成键值map映射表

get_list():生成键值列表

get_tree():生成树型选项集合

get_option():对外提供的统一的选项集合接口

        上述功能实现后,统一选项集合数据服务类就基本完成了。下面是几个具体的选项集合实例。

# 系统用户角色选项处理
optOprRole = List_OptionSet(Role,{'key': 'role_cd','name' : 'rolename','filter' : 'status=0 and roletype=0'},'OprRole')#机构树型选项处理
optBranchTree = Tree_OptionSet(Branchs,{'key': 'id','name' : 'short_name','parent' : 'parent_id','rootid' : 0,'filter' : 'status=0'},'BranchTree')#机构状态
optBranchStatus = OptionSet({0:'正常',1:'停用',9:'废弃'},'BranchStatus')

        前端通过服务请求可以下载选项集合数据,并按个性化的需求对前端组件进行渲染。比如对layui-form中已经有的select、checkbox进行功能增强,也可以自行实现单选树型、多选树型等复合选择域,从而将layui-form的功能再次提升。

        

http://www.lryc.cn/news/591024.html

相关文章:

  • Java 集合框架详解:Collection 接口全解析,从基础到实战
  • 【LeetCode 热题 100】108. 将有序数组转换为二叉搜索树
  • 【Redis 】看门狗:分布式锁的自动续期
  • 如何用Kaggle免费GPU
  • [yotroy.cool] Git 历史迁移笔记:将 Git 项目嵌入另一个仓库子目录中(保留提交记录)
  • 语雀编辑器内双击回车插入当前时间js脚本
  • 【WRFDA第六期】WRFDA 输出文件详述
  • R语言基础| 基本图形绘制(条形图、堆积图、分组图、填充条形图、均值条形图)
  • Spring AI之Prompt开发
  • Web攻防-PHP反序列化Phar文件类CLI框架类PHPGGC生成器TPYiiLaravel
  • Cursor开发步骤
  • 【C++指南】C++ list容器完全解读(四):反向迭代器的巧妙实现
  • 113:路径总和 II
  • Java学习--JVM(2)
  • 基于FPGA的IIC控制EEPROM读写(2)
  • AI算法之图像识别与分类
  • 深入理解Java中的Collections.max()方法
  • 贪心算法(排序)
  • GLM(General Language Model,通用语言模型)
  • 2020717零碎写写
  • 学习OpenCV---显示图片
  • Java集合框架中List常见问题
  • Python爬虫实战:Requests与Selenium详解
  • ESLint 完整功能介绍和完整使用示例演示
  • 产品经理如何描述用户故事
  • Rocky Linux 9 源码包安装php7
  • API开发提速新方案:SmartBear API Hub与ReadyAPI虚拟化整合实践
  • 学习日志预告
  • 学习设计模式《十八》——备忘录模式
  • ThinkPHP8 Windows开发全流程:从搭建到上线