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 08 Python
基于Python开发chrome插件的方法分析
Jul 07 Python
python中的decorator的作用详解
Jul 26 Python
Django+Xadmin构建项目的方法步骤
Mar 06 Python
Python3 tkinter 实现文件读取及保存功能
Sep 12 Python
python 利用pyttsx3文字转语音过程详解
Sep 25 Python
基于python判断目录或者文件代码实例
Nov 29 Python
python socket通信编程实现文件上传代码实例
Dec 14 Python
pytorch自定义二值化网络层方式
Jan 07 Python
python有序查找算法 二分法实例解析
Feb 18 Python
谈谈Python:为什么类中的私有属性可以在外部赋值并访问
Mar 05 Python
Pycharm 使用 Pipenv 新建的虚拟环境(图文详解)
Apr 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中get_headers函数的作用及用法的详细介绍
2013/04/27 PHP
zf框架的registry(注册表)使用示例
2014/03/13 PHP
Windows下编译PHP5.4和xdebug全记录
2015/04/03 PHP
js判断输入是否为正整数、浮点数等数字的函数代码
2010/11/17 Javascript
基于js disabled=&quot;false&quot;不起作用的解决办法
2013/06/26 Javascript
jquery的ajax简单结构示例代码
2014/02/17 Javascript
JavaScript之Object类型介绍
2015/04/01 Javascript
jQuery+PHP+MySQL二级联动下拉菜单实例讲解
2015/10/27 Javascript
使用jQuery实现WordPress中的Ctrl+Enter和@评论回复
2016/05/21 Javascript
超实用的javascript时间处理总结
2016/08/16 Javascript
基于AGS JS开发自定义贴图图层
2017/03/31 Javascript
本地搭建微信小程序服务器的实现方法
2017/10/27 Javascript
Vue 使用Props属性实现父子组件的动态传值详解
2019/11/13 Javascript
关于uniApp editor微信滑动问题
2021/01/15 Javascript
[01:57]2016完美“圣”典风云人物:国士无双专访
2016/12/04 DOTA
python 中文乱码问题深入分析
2011/03/13 Python
python元组操作实例解析
2014/09/23 Python
浅析Python pandas模块输出每行中间省略号问题
2018/07/03 Python
Flask框架响应、调度方法和蓝图操作实例分析
2018/07/24 Python
python bmp转换为jpg 并删除原图的方法
2018/10/25 Python
python 将json数据提取转化为txt的方法
2018/10/26 Python
python学生管理系统开发
2019/01/30 Python
基于python实现计算两组数据P值
2020/07/10 Python
Python模拟登录requests.Session应用详解
2020/11/17 Python
python实现启动一个外部程序,并且不阻塞当前进程
2020/12/05 Python
阿联酋最好的手机、电子产品和家用电器网上商店:Eros Digital Home
2020/08/09 全球购物
西部世纪.net笔试题面试题
2014/04/03 面试题
北大自主招生自荐信
2013/10/19 职场文书
小学三好学生事迹材料
2014/08/15 职场文书
综治维稳工作承诺书
2014/08/30 职场文书
2014年实验室工作总结
2014/12/03 职场文书
北京故宫的导游词
2015/01/31 职场文书
幼儿园个人师德总结
2015/02/06 职场文书
2015年母亲节寄语
2015/03/23 职场文书
解决pytorch 损失函数中输入输出不匹配的问题
2021/06/05 Python
windows server 2012安装FTP并配置被动模式指定开放端口
2022/06/10 Servers