使用django动态创表与查询
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,而实际上去创建模型的时候用的也是这个表名。
#!/usr/bin/env python # -*- coding: UTF-8 -*- 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)
通过以上可以实现简单的动态分表的操作,至于分库使用数据库路由配置即可。
作者:符号哥
微信公众号:左侧为二维码
个人技术网站-编程符号网:http://www.itfh.cn
个人技术网站-IT源码网:http://www.itym.cn
新浪微博:https://weibo.com/u/2814576687
如果你想及时得到个人撰写文章以及著作的消息推送,或者想看看个人推荐的技术资料,可以扫描左边二维码(或者长按识别二维码)关注个人公众号。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

浙公网安备 33010602011771号