前言:
django的分表与动态关联实在是令人扎心,考虑到以后的分表操作,故此debug查看了一波源码,记录一下。
from django.db import models
from django.db import connection
class Book(models.Model):
@classmethod
def get_sharding_model(cls, id, flag=True):
# 简单分表规则
piece = id % 2 + 1
class Meta:
db_table = 'Book_%s' % piece
attrs = {'Meta': Meta, '__module__': cls.__module__}
if not flag:
# 将创建字段的方式改为属性的方式调用
attrs.update({'name': models.CharField(max_length=256)})
return type(Meta.db_table, (models.Model,), attrs)
else:
return type(Meta.db_table, (cls,), attrs)
@classmethod
def sharding_get(cls, id):
model = cls.get_sharding_model(id=id)
return model
@classmethod
def create_table(cls, id):
model = cls.get_sharding_model(id=id, flag=False)
# connection是django初始化的数据库的操作对象,也可以调用相应的api,直接传入sql语句,这里不详细介绍。
with connection.schema_editor() as schema_editor:
schema_editor.create_model(model)
class Meta:
# 声明为抽象类
abstract = True
调用方式:
Book.create_table(4)
Book= Book.sharding_get(3)
print(Book.objects.all())
今天先到这里了,后续再研究了,orm的动态创建着实痛苦,django的封装太深了,包括使用classmeta…
上述虽然实现了,但是还是感觉不方便,后续阅读了源码,发现model类后初始化一个_meta的属性来接收db_table,而实际上去创建模型的时候用的也是这个表名。
from django.db import models
from django.db import connection
class Book(models.Model):
code = models.CharField(max_length=18, unique=True, verbose_name="编码")
name = models.CharField(max_length=18, unique=True, verbose_name="名称")
class Meta:
db_table = 'book'
verbose_name = 'Book'
verbose_name_plural = verbose_name
@classmethod
def set_split_table_rule(cls, id):
piece = id % 2 + 1
return piece
@classmethod
def get_table_name(cls, id):
prefix = cls.set_split_table_rule(id)
return '{}_{}'.format(cls._meta.db_table.split('_')[0], prefix)
@classmethod
def set_model_table_name(cls, id=1):
cls._meta.db_table = cls.get_table_name(id)
return cls._meta.db_table
@staticmethod
def is_exists(table_name):
return table_name in connection.introspection.table_names()
@classmethod
def create_model(cls, id):
table_name = cls.set_model_table_name(id=id)
if not cls.is_exists(table_name):
with connection.schema_editor() as schema_editor:
schema_editor.create_model(cls)
通过以上可以实现简单的动态分表的操作,至于分库使用数据库路由配置即可。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)