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如何import文件夹下的文件(实现方法)
Jan 24 Python
Python命令启动Web服务器实例详解
Feb 23 Python
python2.7无法使用pip的解决方法(安装easy_install)
Apr 03 Python
python 实现A*算法的示例代码
Aug 13 Python
Pycharm无法使用已经安装Selenium的解决方法
Oct 13 Python
启动Atom并运行python文件的步骤
Nov 09 Python
PyQt5 实现字体大小自适应分辨率的方法
Jun 18 Python
解决python执行不输出系统命令弹框的问题
Jun 24 Python
基于python及pytorch中乘法的使用详解
Dec 27 Python
Python pandas如何向excel添加数据
May 22 Python
python 如何调用远程接口
Sep 11 Python
Python Pivot table透视表使用方法解析
Sep 11 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生成带有雪花背景的验证码
2006/10/09 PHP
php生成随机数或者字符串的代码
2008/09/05 PHP
php下防止单引号,双引号在接受页面转义的设置方法
2008/09/25 PHP
PHP5与MySQL数据库操作常用代码 收集
2010/03/21 PHP
在phpstudy集成环境下的nginx服务器下配置url重写
2019/12/02 PHP
FireFox中textNode分片的问题
2007/04/10 Javascript
JavaScript 页面坐标相关知识整理
2010/01/09 Javascript
关于Javascript模块化和命名空间管理的问题说明
2010/12/06 Javascript
nodejs npm package.json中文文档
2014/09/04 NodeJs
JavaScript中toString()方法的使用详解
2015/06/05 Javascript
基于JS2Image实现圣诞树代码
2015/12/24 Javascript
js 获取html5的data属性实现方法
2017/07/28 Javascript
React学习之事件绑定的几种方法对比
2017/09/24 Javascript
[00:36]DOTA2勇士令状莱恩声望物品——冥晶之厄展示
2018/05/25 DOTA
Python中字典映射类型的学习教程
2015/08/20 Python
Python操作使用MySQL数据库的实例代码
2017/05/25 Python
Python_LDA实现方法详解
2017/10/25 Python
Python 和 JS 有哪些相同之处
2017/11/23 Python
对pandas中apply函数的用法详解
2018/04/10 Python
python处理自动化任务之同时批量修改word里面的内容的方法
2019/08/23 Python
Python图像处理库PIL的ImageGrab模块介绍详解
2020/02/26 Python
python MD5加密的示例
2020/10/19 Python
HTML5的语法变化介绍
2013/08/13 HTML / CSS
使用HTML5做的导航条详细步骤
2020/10/19 HTML / CSS
购买限量版收藏品、珠宝和礼品:Bradford Exchange
2016/09/23 全球购物
黄色火烈鸟:De Gele Flamingo
2019/03/18 全球购物
英国护发和美妆在线商店:Klip Shop
2019/03/24 全球购物
巴西本土电商平台:Americanas
2020/06/21 全球购物
网络专业学生个人的自我评价
2013/12/16 职场文书
花店创业计划书范文
2014/02/07 职场文书
大课间体育活动方案
2014/03/12 职场文书
认错检讨书
2014/10/02 职场文书
优秀团支部申报材料
2014/12/26 职场文书
学习杨善洲同志先进事迹心得体会
2016/01/23 职场文书
Java实现扫雷游戏详细代码讲解
2022/05/25 Java/Android
JavaScript parseInt0.0000005打印5原理解析
2022/07/23 Javascript