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网络编程学习笔记(八):XML生成与解析(DOM、ElementTree)
Jun 09 Python
浅谈机器学习需要的了解的十大算法
Dec 15 Python
python+selenium识别验证码并登录的示例代码
Dec 21 Python
centos 安装python3.6环境并配置虚拟环境的详细教程
Feb 22 Python
Python并发之多进程的方法实例代码
Aug 15 Python
PowerBI和Python关于数据分析的对比
Jul 11 Python
详细介绍Python进度条tqdm的使用
Jul 31 Python
用python画一只可爱的皮卡丘实例
Nov 21 Python
matplotlib.pyplot画图并导出保存的实例
Dec 07 Python
Python虚拟环境库virtualenvwrapper安装及使用
Jun 17 Python
Pytorch损失函数nn.NLLLoss2d()用法说明
Jul 07 Python
Python 使用 PyQt5 开发的关机小工具分享
Jul 16 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之XML转数组函数的详解
2013/06/07 PHP
php自定义分页类完整实例
2015/12/25 PHP
Symfony2实现在controller中获取url的方法
2016/03/18 PHP
PHP学习笔记之php文件操作
2016/06/03 PHP
php将文件夹打包成zip文件的简单实现方法
2016/10/04 PHP
PHP面向对象程序设计继承用法简单示例
2018/12/28 PHP
以JSON形式将JS中Array对象数组传至后台的方法
2014/01/06 Javascript
上传图片js判断图片尺寸和格式兼容IE
2014/09/01 Javascript
使表格的标题列可左右拉伸jquery插件封装
2014/11/24 Javascript
对JavaScript的全文搜索实现相关度评分的功能的方法
2015/06/24 Javascript
JS验证IP,子网掩码,网关和MAC的方法
2015/07/02 Javascript
jquery trigger实现联动的方法
2016/02/29 Javascript
bootstrap-datetimepicker实现只显示到日期的方法
2016/11/25 Javascript
AngularJs 利用百度地图API 定位当前位置 获取地址信息
2017/01/18 Javascript
JavaScript实现公历转农历功能示例
2017/02/13 Javascript
3种vue路由传参的基本模式
2018/02/22 Javascript
微信小程序商品详情页的底部弹出框效果
2020/11/16 Javascript
记录一篇关于redux-saga的基本使用过程
2018/08/18 Javascript
vue 实现购物车总价计算
2019/11/06 Javascript
Python接收Gmail新邮件并发送到gtalk的方法
2015/03/10 Python
python实现数独算法实例
2015/06/09 Python
python3.5 email实现发送邮件功能
2018/05/22 Python
python gensim使用word2vec词向量处理中文语料的方法
2019/07/05 Python
python中时间转换datetime和pd.to_datetime详析
2019/08/11 Python
树莓派4B+opencv4+python 打开摄像头的实现方法
2019/10/18 Python
Python语法之精妙的十个知识点(装B语法)
2020/01/18 Python
基于Jquery和Css3代码制作可以缩放的搜索框
2015/11/19 HTML / CSS
html5 Canvas画图教程(6)—canvas里画曲线之arcTo方法
2013/01/09 HTML / CSS
日本索尼音乐商店:Sony Music Shop
2018/07/17 全球购物
当当网软件测试笔试题
2015/11/24 面试题
机关财务管理制度
2014/01/17 职场文书
乡镇党委书记个人整改措施
2014/09/15 职场文书
学生不参加考试检讨书
2015/02/19 职场文书
如何自己动手写SQL执行引擎
2021/06/02 MySQL
mysql中整数数据类型tinyint详解
2021/12/06 MySQL
如何vue使用el-table遍历循环表头和表体数据
2022/04/26 Vue.js