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.py框架实现类似Django的ORM查询的教程
May 02 Python
python实现判断数组是否包含指定元素的方法
Jul 15 Python
Python连接MySQL并使用fetchall()方法过滤特殊字符
Mar 13 Python
Ubuntu 16.04 LTS中源码安装Python 3.6.0的方法教程
Dec 27 Python
简单谈谈Python中的元祖(Tuple)和字典(Dict)
Apr 21 Python
python实现rsa加密实例详解
Jul 19 Python
多个应用共存的Django配置方法
May 30 Python
flask中的wtforms使用方法
Jul 21 Python
简单了解python中对象的取反运算符
Jul 01 Python
在python中做正态性检验示例
Dec 09 Python
python函数定义和调用过程详解
Feb 09 Python
python基于OpenCV模板匹配识别图片中的数字
Mar 31 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
phpQuery占用内存过多的处理方法
2013/11/13 PHP
php中memcache 基本操作实例
2015/05/17 PHP
php封装的连接Mysql类及用法分析
2015/12/10 PHP
PHP不使用递归的无限级分类简单实例
2016/11/05 PHP
PHP对象的浅复制与深复制的实例详解
2017/10/26 PHP
JavaScript的目的分析
2007/01/05 Javascript
EasyUI中的tree用法介绍
2011/11/01 Javascript
javascript查找字符串中出现最多的字符和次数的小例子
2013/10/29 Javascript
分享JavaScript获取网页关闭与取消关闭的事件
2013/12/13 Javascript
基于jquery实现等比缩放图片
2014/12/03 Javascript
JQuery导航菜单选择特效
2016/04/11 Javascript
浅谈JavaScript变量的自动转换和语句
2016/06/12 Javascript
BootStrap 超链接变按钮的实现方法
2016/09/25 Javascript
jquery Easyui Datagrid实现批量操作(编辑,删除,添加)
2017/02/20 Javascript
正则 js分转元带千分符号详解
2017/03/08 Javascript
聊聊Vue.js的template编译的问题
2017/10/09 Javascript
JavaScript 中使用 Generator的方法
2017/12/29 Javascript
浅谈Node.js 子进程与应用场景
2018/01/24 Javascript
nodejs 使用nodejs-websocket模块实现点对点实时通讯
2018/11/28 NodeJs
[01:14]3.19DOTA2发布会 三代刀塔人第二代
2014/03/25 DOTA
使用scrapy实现爬网站例子和实现网络爬虫(蜘蛛)的步骤
2014/01/23 Python
python实现搜索文本文件内容脚本
2018/06/22 Python
Django使用paginator插件实现翻页功能的实例
2018/10/24 Python
Ubuntu下升级 python3.7.1流程备忘(推荐)
2018/12/10 Python
解决webdriver.Chrome()报错:Message:'chromedriver' executable needs to be in Path
2019/06/12 Python
windows上彻底删除jupyter notebook的实现
2020/04/13 Python
Pytorch学习之torch用法----比较操作(Comparison Ops)
2020/06/28 Python
详解Python中的路径问题
2020/09/02 Python
HTML5移动端开发遇见的东西
2019/10/11 HTML / CSS
美国领先的精品家居照明和装饰产品在线零售商:LightsOnline.com
2018/01/23 全球购物
Hotels.com韩国:海外国内旅行所需的酒店和住宿预订网站
2020/05/08 全球购物
工作作风懒散检讨书
2014/10/29 职场文书
2014年药店店长工作总结
2014/11/17 职场文书
2015年师德师风承诺书
2015/01/22 职场文书
护士求职自荐信
2015/03/25 职场文书
Elasticsearch6.2服务器升配后的bug(避坑指南)
2022/09/23 Servers