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 获取本机ip地址的两个方法
Feb 25 Python
Python实现简单的可逆加密程序实例
Mar 05 Python
python编程开发之textwrap文本样式处理技巧
Nov 13 Python
利用标准库fractions模块让Python支持分数类型的方法详解
Aug 11 Python
python实现人脸识别代码
Nov 08 Python
python绘制条形图方法代码详解
Dec 19 Python
python如何通过实例方法名字调用方法
Mar 21 Python
python 通过xml获取测试节点和属性的实例
Mar 31 Python
解决Pycharm无法import自己安装的第三方module问题
May 18 Python
TensorFlow实现模型评估
Sep 07 Python
Python的条件表达式和lambda表达式实例
Jan 31 Python
python脚本第一行如何写
Aug 30 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
swfupload 多文件上传实现代码
2008/08/27 PHP
php实现的遍历文件夹下所有文件,编辑删除
2010/01/05 PHP
Zend的AutoLoad机制介绍
2012/09/27 PHP
使用 PHPMAILER 发送邮件实例应用
2012/11/07 PHP
PHP面向对象五大原则之开放-封闭原则(OCP)详解
2018/04/04 PHP
基于jquery的修改当前TAB显示标题的代码
2010/12/11 Javascript
asp.net网站开发中用jquery实现滚动浏览器滚动条加载数据(类似于腾讯微博)
2012/03/14 Javascript
Javascript原型链和原型的一个误区
2014/10/22 Javascript
javascript文本模板用法实例
2015/07/31 Javascript
js绘制圆形和矩形的方法
2015/08/05 Javascript
使用 stylelint检查CSS_StyleLint
2016/04/28 Javascript
Angular.JS学习之依赖注入$injector详析
2016/10/20 Javascript
详解基于webpack和vue.js搭建开发环境
2017/04/05 Javascript
layui点击按钮添加可编辑的一行方法
2018/08/15 Javascript
ES6 如何改变JS内置行为的代理与反射
2019/02/11 Javascript
Vue模板语法中数据绑定的实例代码
2019/05/17 Javascript
JavaScript eval()函数定义及使用方法详解
2020/07/07 Javascript
vue+AI智能机器人回复功能实现
2020/07/16 Javascript
python线程池的实现实例
2013/11/18 Python
闭包在python中的应用之translate和maketrans用法详解
2014/08/27 Python
Python中列表、字典、元组数据结构的简单学习笔记
2016/03/20 Python
python 捕获 shell/bash 脚本的输出结果实例
2017/01/04 Python
利用numpy实现一、二维数组的拼接简单代码示例
2017/12/15 Python
Python如何基于rsa模块实现非对称加密与解密
2020/01/03 Python
python 将Excel转Word的示例
2021/03/02 Python
英国第一家领先的在线处方眼镜零售商:Glasses Direct
2018/02/23 全球购物
文案策划求职信
2014/03/18 职场文书
护士上岗前培训自我鉴定
2014/04/20 职场文书
党员志愿者活动总结
2014/06/26 职场文书
驾驶员安全责任书
2014/07/22 职场文书
小学生民族团结演讲稿
2014/08/27 职场文书
个人四风问题原因分析及整改措施
2014/09/28 职场文书
工作期间打牌检讨书范文
2014/11/20 职场文书
幼儿园学前班幼儿评语
2014/12/29 职场文书
个人更名证明
2015/06/23 职场文书
HTML怎么设置下划线?html文字加下划线方法
2021/12/06 HTML / CSS