flask/django 动态查询表结构相同表名不同数据的Model实现方法
1.问题
为了控制数据的增长,经常需要分表,数据库中存在多张结构相同,表名相关的表,如:
table_201706
table_201707
table_201708
怎么通过SQLAlchemy或者django查询相关的数据表,而不用每次都创建Model呢
2.解决方法
分别在flask和django下实现,代码如下
2.1flask+sqlalchemy
#-*-coding:utf-8
classNewDynamicModel(object):
"""
动态产生模型和表的对应关系模型
:parambase_cls:基类模型,虚类,如TemplateModel
:paramtb_name:数据库中对应的表名,如tb_test_2017
:return:Modelclass
eg:
'''
classTemplateModel(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')
printTest_2017.query.all()
'''
"""
_instance=dict()
def__new__(cls,base_cls,tb_name):
new_cls_name="%s_To_%s"%(
base_cls.__name__,'_'.join(map(lambdax:x.capitalize(),tb_name.split('_'))))
ifnew_cls_namenotincls._instance:
model_cls=type(new_cls_name,(base_cls,),
{'__tablename__':tb_name})
cls._instance[new_cls_name]=model_cls
returncls._instance[new_cls_name]
Bug:由于新的数据模型是通过type动态创建的,实际module下的py文件并不存在该类的代码,因而在通过pickle等方式序列化的时候,会报找不到类的错误。
Fixbug:通过inspect库,拷贝基类的代码作为副本,并替换tablename属性,写入临时类定义文件,并引入module。
新的方式实现如下:
classNewDynamicModel(object):
"""
动态产生模型和表的对应关系模型
:parambase_cls:基类模型,虚类,如TemplateModel
:paramtb_name:数据库中对应的表名,如tb_test_2017
:return:Modelclass
eg:
'''
classTemplateModel(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')
printTest_2017.query.all()
'''
"""
@staticmethod
defget_import_codes(Model):
"""
获取基类的import依赖
:paramModel:
:return:
"""
module=inspect.getmodule(Model)
all_codelines=inspect.getsourcelines(module)
import_codes=[]
import_codes.append('#-*-coding:utf-8\n')
foriinall_codelines[0]:
match=re.search(r'[from]*[\w|\s]*import[\w|\s]*',i)
ifmatch:
import_codes.append(i)
import_codes.extend(['\n','\n'])
returnimport_codes
@staticmethod
defget_codes(Model,new_model_name,tb_name):
"""
获取基类的实现代码
:paramModel:
:paramnew_model_name:
:paramtb_name:
:return:
"""
codes=inspect.getsourcelines(Model)[0]
result=[]
has_alias_tb_name=False
result.append(codes[0].replace(Model.__name__,new_model_name))
forlineincodes[1:]:
match=re.search(r'\s+__tablename__\s+=\s+\'(?P\w+)\'',line)
abstract=re.search(r'(?P\s+)__abstract__\s+=\s+',line)
ifabstract:
delline
continue
ifmatch:
name=match.groupdict()['name']
line=line.replace(name,tb_name)
has_alias_tb_name=True
result.append(line)
ifnothas_alias_tb_name:
result.append("%s__tablename__='%s'\n"%('',tb_name))
returnresult
@staticmethod
defcreate_new_module(module_name,codes):
"""
创建新表映射类的module文件
:parammodule_name:
:paramcodes:
:return:
"""
f_path=os.path.join(CURRENT_PATH,'_tmp/%s.py'%module_name)
fp=open(f_path,'w')
foriincodes:
fp.write(i)
fp.close()
returnimport_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(lambdax:x.capitalize(),tb_name.split('_'))))
iftb_namenotinengine.table_names():
raiseTableNotExist
ifnew_cls_namenotincls._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
returncls._instance[new_cls_name]
2.2django
#-*-coding:utf-8
fromdjango.dbimportmodels
classNewDynamicModel(object):
"""
动态产生模型和表的对应关系模型
:parambase_cls:基类模型,虚类,如TemplateModel
:paramtb_name:数据库中对应的表名,如tb_test_2017
:return:Modelclass
eg:
'''
classTemplateModel(models.Model):
id=models.AutoField(primary_key=True)
name=models.CharField(max_length=50)
classMeta:
abstract=True
Test_2017=NewDynamicModel(TemplateModel,'tb_test_2017')
printTest_2017.objects.all()
'''
"""
_instance=dict()
def__new__(cls,base_cls,tb_name):
new_cls_name="%s_To_%s"%(
base_cls.__name__,'_'.join(map(lambdax:x.capitalize(),tb_name.split('_'))))
ifnew_cls_namenotincls._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
returncls._instance[new_cls_name]
以上这篇flask/django动态查询表结构相同表名不同数据的Model实现方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。