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的web框架中编写创建日志的程序的教程
Apr 30 Python
批处理与python代码混合编程的方法
May 19 Python
Python实现Youku视频批量下载功能
Mar 14 Python
Python在信息学竞赛中的运用及Python的基本用法(详解)
Aug 15 Python
对python多线程中Lock()与RLock()锁详解
Jan 11 Python
python识别图像并提取文字的实现方法
Jun 28 Python
Python基于WordCloud制作词云图
Nov 29 Python
Keras自定义IOU方式
Jun 10 Python
使用PyWeChatSpy自动回复微信拍一拍功能的实现代码
Jul 02 Python
使用Python实现微信拍一拍功能的思路代码
Jul 09 Python
python 读取、写入txt文件的示例
Sep 27 Python
pandas中对文本类型数据的处理小结
Nov 01 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
PHP 的ArrayAccess接口 像数组一样来访问你的PHP对象
2010/10/12 PHP
用PHP书写安全的脚本代码
2012/02/05 PHP
解析PHP留言本模块主要功能的函数说明(代码可实现)
2013/06/25 PHP
遍历echsop的region表形成缓存的程序实例代码
2016/11/01 PHP
PHP实现上传多图即时显示与即时删除的方法
2017/05/09 PHP
php生出随机字符串
2017/07/06 PHP
关于php unset对json_encode的影响详解
2018/11/14 PHP
php创建多级目录与级联删除文件的方法示例
2019/09/12 PHP
jQuery 在光标定位的地方插入文字的插件
2012/05/10 Javascript
Jquery 数据选择插件Pickerbox使用介绍
2012/08/24 Javascript
使用js判断控件是否获得焦点
2014/01/03 Javascript
Javascript简写条件语句(推荐)
2016/06/12 Javascript
Bootstrap Metronic完全响应式管理模板学习笔记
2016/07/08 Javascript
jQuery增加、删除及修改select option的方法
2016/08/19 Javascript
BootStrap 图标icon符号图标glyphicons不正常显示的快速解决办法
2016/12/08 Javascript
JS组件系列之MVVM组件 vue 30分钟搞定前端增删改查
2017/04/28 Javascript
基于nodejs实现微信支付功能
2017/12/20 NodeJs
angular4 获取wifi列表中文显示乱码问题的解决
2018/10/20 Javascript
在Create React App中使用CSS Modules的方法示例
2019/01/15 Javascript
解决Layui数据表格的宽高问题
2019/09/28 Javascript
微信小游戏中three.js离屏画布的示例代码
2020/10/12 Javascript
Python中类型关系和继承关系实例详解
2015/05/25 Python
Python实现读写INI配置文件的方法示例
2018/06/09 Python
详解Python正则表达式re模块
2019/03/19 Python
python @classmethod 的使用场合详解
2019/08/23 Python
python求一个字符串的所有排列的实现方法
2020/02/04 Python
解决python图像处理图像赋值后变为白色的问题
2020/06/04 Python
Python虚拟环境库virtualenvwrapper安装及使用
2020/06/17 Python
Selenium python时间控件输入问题解决方案
2020/07/22 Python
代领报检证委托书范本
2014/10/11 职场文书
党员学习中国梦心得体会
2016/01/05 职场文书
2019暑期安全倡议书!
2019/06/27 职场文书
2019年汽车租赁合同范本!
2019/08/12 职场文书
Redis延迟队列和分布式延迟队列的简答实现
2021/05/13 Redis
Golang 字符串的常见操作
2022/04/19 Golang
PYTHON InceptionV3模型的复现详解
2022/05/06 Python