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 获取新浪微博的最新公共微博实例分享
Jul 03 Python
Pyhton中单行和多行注释的使用方法及规范
Oct 11 Python
Python 递归函数详解及实例
Dec 27 Python
Python判断是否json是否包含一个key的方法
Dec 31 Python
Django model select的多种用法详解
Jul 16 Python
Django的性能优化实现解析
Jul 30 Python
python关闭占用端口方式
Dec 17 Python
PyTorch的SoftMax交叉熵损失和梯度用法
Jan 15 Python
Python进程Multiprocessing模块原理解析
Feb 28 Python
Django REST framwork的权限验证实例
Apr 02 Python
Python 排序最长英文单词链(列表中前一个单词末字母是下一个单词的首字母)
Dec 14 Python
Python抖音快手代码舞(字符舞)的实现方法
Feb 07 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实现过滤字符串中的中文和数字实例
2015/07/29 PHP
PHP简单的MVC框架实现方法
2015/12/01 PHP
jQuery中文入门指南,翻译加实例,jQuery的起点教程
2007/01/13 Javascript
JavaScript中两种链式调用实现代码
2011/01/12 Javascript
jQuery对表单的操作代码集合
2011/04/06 Javascript
JavaScript判断一个URL链接是否有效的实现方法
2011/10/08 Javascript
IE中jquery.form中ajax提交没反应解决方法分享
2012/09/11 Javascript
用js实现table单元格高宽调整,兼容合并单元格(兼容IE6、7、8、FF)实例
2013/06/25 Javascript
javascript将url中的参数加密解密代码
2014/11/17 Javascript
jquery 插件实现多行文本框[textarea]自动高度
2015/03/04 Javascript
node.js中格式化数字增加千位符的几种方法
2015/07/03 Javascript
jQuery原理系列-css选择器的简单实现
2016/06/07 Javascript
使用smartupload组件实现jsp+jdbc上传下载文件实例解析
2017/01/05 Javascript
JavaScript中数组Array方法详解
2017/02/27 Javascript
微信小程序 开发MAP(地图)实例详解
2017/06/27 Javascript
Angular.js初始化之ng-app的自动绑定与手动绑定详解
2017/07/31 Javascript
微信小程序三级联动选择器使用方法
2020/05/19 Javascript
element-ui 时间选择器限制范围的实现(随动)
2019/01/09 Javascript
Vue开发之封装上传文件组件与用法示例
2019/04/25 Javascript
浅谈Vue开发人员的7个最好的VSCode扩展
2021/01/20 Vue.js
python爬虫框架scrapy实战之爬取京东商城进阶篇
2017/04/24 Python
Python3中的列表生成式、生成器与迭代器实例详解
2018/06/11 Python
python3 pillow模块实现简单验证码
2019/10/31 Python
python 实现弹球游戏的示例代码
2020/11/17 Python
html5自带表单验证体验优化及提示气泡修改功能
2017/09/12 HTML / CSS
美国最大的船只买卖在线市场:Boat Trader
2018/08/04 全球购物
人事部专员岗位职责
2014/03/04 职场文书
大学生职业生涯规划书参考模板
2014/03/05 职场文书
2014年计生标语
2014/06/23 职场文书
关于青春的演讲稿800字
2014/08/22 职场文书
县人大领导班子四风对照检查材料思想汇报
2014/10/09 职场文书
行政文员岗位职责
2015/02/04 职场文书
高一数学教学反思
2016/02/18 职场文书
Nginx中break与last的区别详析
2021/03/31 Servers
Python实现拼音转换
2021/06/07 Python
Spring事务管理下synchronized锁失效问题的解决方法
2022/03/31 Java/Android