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比较文件夹比另一同名文件夹多出的文件并复制出来的方法
Mar 05 Python
使用Python编写一个最基础的代码解释器的要点解析
Jul 12 Python
Python使用装饰器进行django开发实例代码
Feb 06 Python
Python判断是否json是否包含一个key的方法
Dec 31 Python
对Python之gzip文件读写的方法详解
Feb 08 Python
对Python定时任务的启动和停止方法详解
Feb 19 Python
django的settings中设置中文支持的实现
Apr 28 Python
python中的协程深入理解
Jun 10 Python
python绘图模块matplotlib示例详解
Jul 26 Python
使用python模拟高斯分布例子
Dec 09 Python
python集合能干吗
Jul 19 Python
Python实现敏感词过滤的4种方法
Sep 12 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学习之数据类型之间的转换介绍
2011/06/09 PHP
php中将html中的br换行符转换为文本输入中的换行符
2013/03/26 PHP
php中的比较运算符详解
2013/10/28 PHP
php批量修改表结构实例
2017/05/24 PHP
PHP闭包定义与使用简单示例
2018/04/13 PHP
[JS源码]超长文章自动分页(客户端版)
2007/01/09 Javascript
JavaScript开发规范要求(规范化代码)
2010/08/16 Javascript
JavaScript与DOM组合动态创建表格实例
2012/12/23 Javascript
jQuery建立一个按字母顺序排列的友好页面索引(兼容IE6/7/8)
2013/02/26 Javascript
ajaxFileUpload.js插件支持多文件上传的方法
2014/09/02 Javascript
关于编写性能高效的javascript事件的技术
2014/11/28 Javascript
JavaScript函数的调用以及参数传递
2015/10/21 Javascript
自己动手写的javascript前端等待控件
2015/10/30 Javascript
javascript RegExp 使用说明
2016/05/21 Javascript
jQuery模拟下拉框选择对应菜单的内容
2017/03/07 Javascript
基于vue实现网站前台的权限管理(前后端分离实践)
2018/01/13 Javascript
Nodejs对postgresql基本操作的封装方法
2019/02/20 NodeJs
JavaScript Array对象使用方法解析
2019/09/24 Javascript
JS常见错误(Error)及处理方案详解
2020/07/02 Javascript
[53:15]Mineski vs iG 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
Python中operator模块的操作符使用示例总结
2016/06/28 Python
Python 专题二 条件语句和循环语句的基础知识
2017/03/19 Python
解决Python2.7读写文件中的中文乱码问题
2018/04/12 Python
Tensorflow之MNIST CNN实现并保存、加载模型
2020/06/17 Python
美国战术品牌:5.11 Tactical
2019/05/01 全球购物
Happy Socks英国官网:购买五颜六色的袜子
2020/11/03 全球购物
如何做好总经理助理
2013/11/12 职场文书
标准自荐信范文
2014/01/29 职场文书
感恩教育月活动总结
2014/07/07 职场文书
小学教师暑期培训方案
2014/08/28 职场文书
2014年化验员工作总结
2014/11/18 职场文书
工作表扬信范文
2015/01/17 职场文书
2015大学生暑期实习报告
2015/07/13 职场文书
pandas取dataframe特定行列的实现方法
2021/05/24 Python
Java数组与堆栈相关知识总结
2021/06/29 Java/Android
Python语言内置数据类型
2022/02/24 Python