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原始字符串(raw strings)用法实例
Oct 13 Python
常见python正则用法的简单实例
Jun 21 Python
Python使用struct处理二进制的实例详解
Sep 11 Python
python微信跳一跳系列之棋子定位像素遍历
Feb 26 Python
Python爬虫之网页图片抓取的方法
Jul 16 Python
Django如何自定义model创建数据库索引的顺序
Jun 20 Python
centos 安装Python3 及对应的pip教程详解
Jun 28 Python
Django中自定义admin Xadmin的实现代码
Aug 09 Python
Python实现微信翻译机器人的方法
Aug 13 Python
python+pygame实现坦克大战
Sep 10 Python
wxPython修改文本框颜色过程解析
Feb 14 Python
Python中的np.argmin()和np.argmax()函数用法
Jun 02 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验证码类代码( 最新修改,完全定制化! )
2010/12/02 PHP
PHP表单提交表单名称含有点号(.)则会被转化为下划线(_)
2011/12/14 PHP
TP5框架实现一次选择多张图片并预览的方法示例
2020/04/04 PHP
Javascript select下拉框操作常用方法
2009/11/09 Javascript
Javascript在IE或Firefox下获取鼠标位置的代码
2009/12/18 Javascript
Javascript页面添加到收藏夹的简单方法
2013/08/07 Javascript
Microsfot .NET Framework4.0框架 安装失败的解决方法
2013/08/14 Javascript
当json键为数字时的取值方法解析
2013/11/15 Javascript
文本框(input)获取焦点(onfocus)时样式改变的示例代码
2014/01/10 Javascript
jquery $(&quot;#variable&quot;) 循环改变variable的值示例
2014/02/23 Javascript
jquery实现增加删除行的方法
2015/02/03 Javascript
Jquery动态添加输入框的方法
2015/05/29 Javascript
JavaScript Math 对象常用方法总结
2016/04/28 Javascript
js的各种排序算法实现(总结)
2016/07/23 Javascript
深入浅析JS Function()构造函数
2016/08/22 Javascript
VueJs路由跳转——vue-router的使用详解
2017/01/10 Javascript
基于Vue实例生命周期(全面解析)
2017/08/16 Javascript
js实现以最简单的方式将数组元素添加到对象中的方法
2017/12/20 Javascript
react router4+redux实现路由权限控制的方法
2018/05/03 Javascript
python概率计算器实例分析
2015/03/25 Python
python程序运行进程、使用时间、剩余时间显示功能的实现代码
2019/07/11 Python
Win10里python3创建虚拟环境的步骤
2020/01/31 Python
Python如何读写二进制数组数据
2020/08/01 Python
详解CSS3选择器的使用方法汇总
2015/11/24 HTML / CSS
HTML5 FileReader对象的具体使用方法
2020/05/22 HTML / CSS
美国最大的宠物用品零售商:PetSmart
2016/11/14 全球购物
罗马尼亚购物网站:Vivantis.ro
2019/07/20 全球购物
添柏岚英国官方网站:Timberland英国
2019/11/28 全球购物
新西兰最大的天然保健及护肤品网站:HealthPost(直邮中国)
2021/02/13 全球购物
电气工程师岗位职责
2014/01/01 职场文书
工程项目建议书范文
2014/03/12 职场文书
暑期教师培训方案
2014/06/07 职场文书
2015年安康杯竞赛活动总结
2015/03/26 职场文书
医生行业员工的辞职信
2019/06/24 职场文书
详解Python如何批量采集京东商品数据流程
2022/01/22 Python
Python实现批量自动整理文件
2022/03/16 Python