flask/django 动态查询表结构相同表名不同数据的Model实现方法


Posted in Python onAugust 29, 2019

1.问题

为了控制数据的增长,经常需要分表,数据库中存在多张结构相同,表名相关的表,如:

table_201706
table_201707
table_201708

怎么通过SQLAlchemy 或者django查询相关的数据表,而不用每次都创建Model呢

2.解决方法

分别在flask和django下实现,代码如下

2.1 flask+sqlalchemy

# -*-coding:utf-8


class NewDynamicModel(object):
 """
 动态产生模型和表的对应关系模型
 :param base_cls: 基类模型,虚类,如TemplateModel
 :param tb_name: 数据库中对应的表名, 如tb_test_2017
 :return: Model class
 eg:
 '''
 class TemplateModel(db.Model):
  __abstract__ = True
  id = db.Column(db.Integer(), autoincrement=True, primary_key=True)
  name = db.Column(db.VARCHAR(32), nullable=False)

 Test_2017 = NewDynamicModel(TemplateModel, 'tb_test_2017')
 print Test_2017.query.all()
 '''
 """
 _instance = dict()

 def __new__(cls, base_cls, tb_name):
  new_cls_name = "%s_To_%s" % (
   base_cls.__name__, '_'.join(map(lambda x:x.capitalize(),tb_name.split('_'))))

  if new_cls_name not in cls._instance:
   model_cls = type(new_cls_name, (base_cls,),
        {'__tablename__': tb_name})
   cls._instance[new_cls_name] = model_cls

  return cls._instance[new_cls_name]

Bug:由于新的数据模型是通过type动态创建的,实际module 下的py文件并不存在该类的代码,因而在通过pickle等方式序列化的时候,会报找不到类的错误。

Fixbug: 通过inspect库,拷贝基类的代码作为副本,并替换tablename 属性,写入临时类定义文件,并引入module。

新的方式实现如下:

class NewDynamicModel(object):
 """
 动态产生模型和表的对应关系模型
 :param base_cls: 基类模型,虚类,如TemplateModel
 :param tb_name: 数据库中对应的表名, 如tb_test_2017
 :return: Model class
 eg:
 '''
 class TemplateModel(db.Model):
  __abstract__ = True
  id = db.Column(db.Integer(), autoincrement=True, primary_key=True)
  name = db.Column(db.VARCHAR(32), nullable=False)



 Test_2017 = NewDynamicModel(TemplateModel, 'tb_test_2017')
 print Test_2017.query.all()
 '''
 """

 @staticmethod
 def get_import_codes(Model):
  """
  获取基类的import依赖
  :param Model:
  :return:
  """
  module = inspect.getmodule(Model)
  all_codelines = inspect.getsourcelines(module)
  import_codes = []
  import_codes.append('# -*-coding:utf-8\n')
  for i in all_codelines[0]:
   match = re.search(r'[from]*[\w|\s]*import [\w|\s]*', i)
   if match:
    import_codes.append(i)
  import_codes.extend(['\n', '\n'])

  return import_codes

 @staticmethod
 def get_codes(Model, new_model_name, tb_name):
  """
  获取基类的实现代码
  :param Model:
  :param new_model_name:
  :param tb_name:
  :return:
  """
  codes = inspect.getsourcelines(Model)[0]
  result = []
  has_alias_tb_name = False
  result.append(codes[0].replace(Model.__name__, new_model_name))
  for line in codes[1:]:
   match = re.search(r'\s+__tablename__\s+=\s+\'(?P<name>\w+)\'', line)
   abstract = re.search(r'(?P<indent>\s+)__abstract__\s+=\s+', line)
   if abstract:
    del line
    continue

   if match:
    name = match.groupdict()['name']
    line = line.replace(name, tb_name)
    has_alias_tb_name = True

   result.append(line)

  if not has_alias_tb_name:
   result.append("%s__tablename__ = '%s'\n" % (' ', tb_name))

  return result

 @staticmethod
 def create_new_module(module_name, codes):
  """
  创建新表映射类的module文件
  :param module_name:
  :param codes:
  :return:
  """
  f_path = os.path.join(CURRENT_PATH, '_tmp/%s.py' % module_name)
  fp = open(f_path, 'w')
  for i in codes:
   fp.write(i)
  fp.close()

  return import_module('sync_session.models._tmp.%s' % module_name)

 _instance = dict()

 def __new__(cls, base_cls, tb_name):
  new_cls_name = "%s_To_%s" % (
   base_cls.__name__, ''.join(map(lambda x: x.capitalize(), tb_name.split('_'))))

  if tb_name not in engine.table_names():
   raise TableNotExist

  if new_cls_name not in cls._instance:
   import_codes = cls.get_import_codes(base_cls)
   class_codes = cls.get_codes(base_cls, new_cls_name, tb_name)
   import_codes.extend(class_codes)
   new_module_name = new_cls_name.lower()
   new_module = cls.create_new_module(new_module_name, import_codes)
   model_cls = getattr(new_module, new_cls_name)

   cls._instance[new_cls_name] = model_cls

  return cls._instance[new_cls_name]

2.2 django

# -*-coding:utf-8
from django.db import models


class NewDynamicModel(object):
 """
 动态产生模型和表的对应关系模型
 :param base_cls: 基类模型,虚类,如TemplateModel
 :param tb_name: 数据库中对应的表名, 如tb_test_2017
 :return: Model class
 eg:
 '''
 class TemplateModel(models.Model):
  id = models.AutoField(primary_key=True)
  name = models.CharField(max_length=50)

  class Meta:
   abstract = True

 Test_2017 = NewDynamicModel(TemplateModel, 'tb_test_2017')
 print Test_2017.objects.all()
 '''
 """
 _instance = dict()

 def __new__(cls, base_cls, tb_name):
  new_cls_name = "%s_To_%s" % (
   base_cls.__name__, '_'.join(map(lambda x:x.capitalize(),tb_name.split('_'))))

  if new_cls_name not in cls._instance:
   new_meta_cls = base_cls.Meta
   new_meta_cls.db_table = tb_name
   model_cls = type(new_cls_name, (base_cls,),
        {'__tablename__': tb_name, 'Meta': new_meta_cls, '__module__': cls.__module__})
   cls._instance[new_cls_name] = model_cls

  return cls._instance[new_cls_name]

以上这篇flask/django 动态查询表结构相同表名不同数据的Model实现方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
浅谈python中的面向对象和类的基本语法
Jun 13 Python
分享一个可以生成各种进制格式IP的小工具实例代码
Jul 28 Python
python使用itchat库实现微信机器人(好友聊天、群聊天)
Jan 04 Python
Python hashlib模块用法实例分析
Jun 12 Python
3个用于数据科学的顶级Python库
Sep 29 Python
实例讲解python中的序列化知识点
Oct 08 Python
python使用turtle库绘制奥运五环
Feb 24 Python
在pycharm中创建django项目的示例代码
May 28 Python
升级keras解决load_weights()中的未定义skip_mismatch关键字问题
Jun 12 Python
Python和Bash结合在一起的方法
Nov 13 Python
python 用Matplotlib作图中有多个Y轴
Nov 28 Python
Python matplotlib多个子图绘制整合
Apr 13 Python
深入了解python中元类的相关知识
Aug 29 #Python
Django shell调试models输出的SQL语句方法
Aug 29 #Python
python实现文件的分割与合并
Aug 29 #Python
Python配置文件处理的方法教程
Aug 29 #Python
浅谈django url请求与数据库连接池的共享问题
Aug 29 #Python
python 进程的几种创建方式详解
Aug 29 #Python
python 列表推导式使用详解
Aug 29 #Python
You might like
压力如何影响浓缩咖啡品质
2021/03/03 咖啡文化
php ctype函数中文翻译和示例
2014/03/21 PHP
JQuery CSS样式控制 学习笔记
2009/07/23 Javascript
高效的表格行背景隔行变色及选定高亮的JS代码
2010/12/04 Javascript
jQuery源码分析-04 选择器-Sizzle-工作原理分析
2011/11/14 Javascript
基于jQuery的Web上传插件Uploadify使用示例
2016/05/19 Javascript
基于JS如何实现给字符加千分符(65,541,694,158)
2016/08/03 Javascript
JavaScript编码风格指南(中文版)
2016/08/26 Javascript
值得分享的bootstrap table实例
2016/09/22 Javascript
Bootstrap 响应式实用工具实例详解
2017/03/29 Javascript
VUE axios发送跨域请求需要注意的问题
2017/07/06 Javascript
angularjs实现猜大小功能
2017/10/23 Javascript
Vue 过滤器filters及基本用法
2017/12/26 Javascript
Vue三种常用传值示例(父传子、子传父、非父子)
2018/07/24 Javascript
详解Angular6学习笔记之主从组件
2018/09/05 Javascript
Vue运用transition实现过渡动画
2019/05/06 Javascript
对Layer UI 模块化的用法详解
2019/09/26 Javascript
vue-property-decorator用法详解
2019/12/12 Javascript
JavaScript setInterval()与setTimeout()计时器
2019/12/27 Javascript
vue如何实现动态加载脚本
2020/02/05 Javascript
Vue基于localStorage存储信息代码实例
2020/11/16 Javascript
python非递归全排列实现方法
2017/04/10 Python
Python文件常见操作实例分析【读写、遍历】
2018/12/10 Python
在Pycharm terminal中字体大小设置的方法
2019/01/16 Python
python输出决策树图形的例子
2019/08/09 Python
[原创]赚疯了!转手立赚800+?大佬的python「抢茅台脚本」使用教程
2021/01/12 Python
Linux中如何用命令创建目录
2016/12/02 面试题
浪漫婚礼主持词
2014/03/14 职场文书
工地材料员岗位职责
2015/04/11 职场文书
投标售后服务承诺书
2015/04/29 职场文书
2015年社区科普工作总结
2015/05/13 职场文书
2015年中学校长工作总结
2015/05/19 职场文书
Java方法重载和方法重写的区别到底在哪?
2021/06/11 Java/Android
React列表栏及购物车组件使用详解
2021/06/28 Javascript
pd.DataFrame中的几种索引变换的实现
2022/06/16 Python
纯CSS实现一个简单步骤条的示例代码
2022/07/15 HTML / CSS