flask/django 动态查询表结构相同表名不同数据的Model实现方法

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实现方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 详解Django model update的各种用法介绍

    Django开发过程中对表(model)的增删改查是最常用的功能之一,本文介绍笔者在使用model update过程中遇到的那些事 [ 运行环境:Django2.0 ] model update常规用法 假如我们的表结构是这样的 class User(models.Model): username = models.CharField(max_length=255, unique=True, verbose_name='用户名') is_active = models.BooleanField(

  • 通过数据库向Django模型添加字段的示例

    首先借用书本(book)的这个数据模型: from django.db import models class Publisher(models.Model): name = models.CharField(max_length=30) address = models.CharField(max_length=50) city = models.CharField(max_length=60) state_province = models.CharField(max_length=30)

  • Django-Model数据库操作(增删改查、连表结构)详解

    一.数据库操作 1.创建model表 基本结构 from django.db import models class userinfo(models.Model): #如果没有models.AutoField,默认会创建一个id的自增列 name = models.CharField(max_length=30) email = models.EmailField() memo = models.TextField() 更多字段: 1.models.AutoField 自增列= int(11)

  • Python框架Flask的基本数据库操作方法分析

    本文实例讲述了Python框架Flask的基本数据库操作方法.分享给大家供大家参考,具体如下: 数据库操作在web开发中扮演着一个很重要的角色,网站中很多重要的信息都需要保存到数据库中.如用户名.密码等等其他信息.Django框架是一个基于MVT思想的框架,也就是说他本身就已经封装了Model类,可以在文件中直接继承过来.但是在Flask中,并没有把Model类封装好,需要使用一个扩展包,Flask-SQLAlchemy.它是一个对数据库的抽象,让开发者不用这些编写SQL语句,而是使用其提供的接

  • flask/django 动态查询表结构相同表名不同数据的Model实现方法

    1.问题 为了控制数据的增长,经常需要分表,数据库中存在多张结构相同,表名相关的表,如: table_201706 table_201707 table_201708 怎么通过SQLAlchemy 或者django查询相关的数据表,而不用每次都创建Model呢 2.解决方法 分别在flask和django下实现,代码如下 2.1 flask+sqlalchemy # -*-coding:utf-8 class NewDynamicModel(object): """ 动态产生

  • Postgresql删除数据库表中重复数据的几种方法详解

    一直使用Postgresql数据库,有一张表是这样的: DROP TABLE IF EXISTS "public"."devicedata"; CREATE TABLE "public"."devicedata" ( "Id" varchar(200) COLLATE "pg_catalog"."default" NOT NULL, "DeviceId&qu

  • asp实现批量插入表单中的数据到数据库的方法

    input域指定相同name属性,而后你requet.form来这个值是以逗号分割的字符串,分割字符串为数组,然后遍历,并执行sql语句.

  • Flask和Django框架中自定义模型类的表名、父类相关问题分析

    本文实例分析了Flask和Django框架中自定义模型类的表名.父类相关问题.分享给大家供大家参考,具体如下: 一. Flask和Django中定义表名(执行迁移后生成)的方式和flask是不同的: 1. Django中表名的定义方式,以代码为例说明 class User(AbstractUser): # 继承自认证系统模型类 """用户模型类""" mobile = modles.CharField(max_length=11, mix_len

  • Sql查询MySql数据库中的表名和描述表中字段(列)信息

    下面为大家介绍利用SQL查询语句获取Mysql数据库中表的表名,表描述.字段ID.字段名.数据类型.长度.精度.是否可以为null.默认值.是否自增.是否是主键.列描述 一.查询表信息(表名/表描述) SELECT table_name name,TABLE_COMMENT value FROM INFORMATION_SCHEMA.TABLES WHERE table_type='base table' and table_schema = '数据库名' order by table_name

  • Entity Framework Core表名映射

    表名映射 我们知道:如果是在默认情况下,使用EFCore Code First的方式生成的表名跟数据上下文类中定义的实体属性的名称是一致的,例如: public DbSet<Blog> Bloges123 { get; set; } 这里定义的属性名称是Bloges123,那么最后数据库中生成的表名也叫Bloges123.看下面的测试. 我们首先添加迁移,每次迁移都会生成一个对应的迁移记录类,代码如下图所示: 可以看到,这里显示创建表的名称就是Bloges123.最后更新数据库,更新完成以后查

  • MySQL数据库之数据表操作DDL数据定义语言

    目录 一.创建数据表 二.查询数据表 三. 删除数据表 四.修改数据表以及字段 一.创建数据表 数据表:一个二维的表格,一个表格是由多列组成,表格中的每一类称之为表格的字段 以上述学生信息表格为例在MySQL数据库中创建一张表格,语句如下(注:创建前应选择相应的数据库): create table students( stu_num char(8) not null unique, stu_name varchar(20) not null, stu_gender char(2) not nul

  • Mybatis 动态表名+Map参数传递+批量操作详解

    需求: 之前项目一个变动,需要对3张mysql数据库表数据进行清洗,3张表表名不同,表结构完全相同,需要对这3张表进行相同的增.改.查动作,一开始比较紧急先对一张表进行操作,后来复制了3个一样的 service.dao.mapper等.后来对代码进行优化,研究了一下动态表名的处理. 1,查询操作: 查询操作只需要传入动态表名的时候,传递参数仍然是map mapper.xml内,需要使用statementType="STATEMENT",采用非预编译模式 mapper.xml内,动态表名

  • mybatis-plus动态表名实现方法

    目录 1.使用场景 2.一定要时常注意工具的更新,不吃亏 3.对mybatis-plus进行升级 4.将原来的mybatis的插件配置调整成新版本的,并添加上动态表名的模块 5.运行一下 6. 需要注意的地方 1.使用场景 一个mybatis entity 对应多张表(表明不同的表–> 多张表结构一致只有表名称不同),在使用时,可以动态映射表名称.比如:按照时间分表,某些业务冷热数据分离后数据存在不同的表中等 2.一定要时常注意工具的更新,不吃亏 因为工作需要,最近需要实现一个类似如下业务等功能

  • MyBatis拦截器动态替换表名的方法详解

    目录 写在前面 一.Mybatis Interceptor 拦截器接口和注解 二.实现思路 三.代码实现 四.运行结果 写在最后 参考资料 写在前面 今天收到一个需求,根据请求方的不同,动态的切换表名(涵盖SELECT,INSERT,UPDATE操作).几张新表和旧表的结构完全一致,但是分开维护.看到需求第一反应是将表名提出来当${tableName}参数,然后AOP拦截判断再替换表名.但是后面看了一下这几张表在很多mapper接口都有使用,其中还有一些复杂的连接查询,提取tableName当参

随机推荐