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入门篇之文件
Oct 20 Python
浅谈Python中数据解析
May 05 Python
Django imgareaselect手动剪切头像实现方法
May 26 Python
python爬虫入门教程--HTML文本的解析库BeautifulSoup(四)
May 25 Python
python脚本监控Tomcat服务器的方法
Jul 06 Python
Python2和Python3中urllib库中urlencode的使用注意事项
Nov 26 Python
详解python编译器和解释器的区别
Jun 24 Python
Python 分发包中添加额外文件的方法
Aug 16 Python
阿里云ECS服务器部署django的方法
Aug 29 Python
OpenCV模板匹配matchTemplate的实现
Oct 18 Python
Python标准库json模块和pickle模块使用详解
Mar 10 Python
解决Keras TensorFlow 混编中 trainable=False设置无效问题
Jun 28 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怎样调用MSSQL的存储过程
2006/10/09 PHP
coreseek 搜索英文的问题详解
2013/06/08 PHP
PHP CodeIgniter框架的工作原理研究
2015/03/30 PHP
js阻止事件追加的具体实现
2014/10/15 Javascript
javascript中几个容易混淆的概念总结
2015/04/14 Javascript
分析js闭包引起的事件注册问题
2016/03/29 Javascript
jquery简单插件制作(fn.extend)完整实例
2016/05/24 Javascript
jQuery实现按钮点击遮罩加载及处理完后恢复的效果
2016/06/07 Javascript
老生常谈onBlur事件与onfocus事件(js)
2016/07/09 Javascript
ASP.NET jquery ajax传递参数的实例
2016/11/02 Javascript
使用jsonp实现跨域获取数据实例讲解
2016/12/25 Javascript
vue实现ToDoList简单实例
2017/02/07 Javascript
JavaScript评论点赞功能的实现方法
2017/03/13 Javascript
AngularJS 实现点击按钮获取验证码功能实例代码
2017/07/13 Javascript
vue组件父与子通信详解(一)
2017/11/07 Javascript
在vue中,v-for的索引index在html中的使用方法
2018/03/06 Javascript
AngularJS与后端php的数据交互方法
2018/08/13 Javascript
Angular实现svg和png图片下载实现
2019/05/05 Javascript
axios异步提交表单数据的几种方法
2019/08/11 Javascript
React 父子组件通信的实现方法
2019/12/05 Javascript
vue 公共列表选择组件,引用Vant-UI的样式方式
2020/11/02 Javascript
测试、预发布后用python检测网页是否有日常链接
2014/06/03 Python
Python模仿POST提交HTTP数据及使用Cookie值的方法
2014/11/10 Python
ubuntu安装sublime3并配置python3环境的方法
2018/03/15 Python
解决pycharm无法识别本地site-packages的问题
2018/10/13 Python
pandas 数据归一化以及行删除例程的方法
2018/11/10 Python
python多进程(加入进程池)操作常见案例
2019/10/21 Python
Python3 xml.etree.ElementTree支持的XPath语法详解
2020/03/06 Python
numpy库ndarray多维数组的维度变换方法(reshape、resize、swapaxes、flatten)
2020/04/28 Python
python如何编写win程序
2020/06/08 Python
美国户外烹饪产品购物网站:Outdoor Cooking
2020/01/10 全球购物
新西兰最大的天然保健及护肤品网站:HealthPost(直邮中国)
2021/02/13 全球购物
中国梦口号
2014/06/13 职场文书
领导干部保密承诺书
2014/08/30 职场文书
2014年最新领导班子整改方案
2014/09/27 职场文书
公司档案管理制度
2015/08/05 职场文书