前言
正式开始上班了。工作中遇到个问题,就是在Django中要根据应用名进行动态分表。实现时遇到点问题,在这里记录下整体的思路和实现。
具体任务
利用Django的ORM机制根据应用名实现动态分表。简单来说就是保持Model结构不变的情况下,可以在服务器运行时,动态在应用名对应的表内进行数据库操作。每个应用独立出一张表。所有表的结果相同。
思路
Django中的每个Model对应数据库中的一张表。每个Model也就是一个继承自django.models.Model的Python类。每个类正常是包含三个部分:
- 类属性。每个类属性对应表中的一个字段。
- Meta嵌套类。Meta嵌套类中也包含了一些类属性。常见的有 db_table 和 app_label。db_table定义了这个Python类对应的表名。app_label则定义了这个Python类对应的应用名。
- 类方法/实例方法。这些方法不是必须有的。可以根据需要进行编写。
如上所言,类属性定义了表的结构。而Meta嵌套类则决定了表名。
因此如果能够在代码中根据应用名动态切换Meta嵌套类的类属性,也就实现了根据应用名动态分表的功能。
实际实现时,就是定义一个类方法,根据应用名,设定Meta嵌套类具体类属性,然后使用type基于原有的Python类的类属性和新的Meta嵌套类创建一个新类。使用新类基于ORM机制操作数据表。
具体实现
from django.db import models
class AppLog(models.Model):
full_name = models.CharField(max_length=2048)
creator = models.CharField(max_length=30)
create_time = models.DateTimeField(auto_now_add=True)
class Meta:
db_table = "file_log"
app_label = 'app'
@classmethod
def get_app_log_model(cls, app_name):
class Meta:
db_table = '{}_{}'.format(app_name, cls._meta.db_table)
app_label = cls._meta.app_label
attrs = {
'Meta': Meta,
'__module__': cls.__module__,
}
return type(cls._meta.db_table, (AppLog, ), attrs)
写完后,记得makemigrations 和 migrate同步下数据库。
走到这,是不是以为大功告成了。
来,测试下。


执行报错了。
但是从报错信息来看,ORM操作数据表时已经定向到test_file_log这张表。只不过这张表不存在。
看到这里,就会产生一点疑问,明明已经同步过数据库了,为什么数据表会不存在呢,不是说好的自动创建。
这里其实就涉及到另外一个问题了。Django的makemigrations 和 migrate机制针对的都是明明白白写清楚的,继承自django.models.Model类的Python类。而本文中动态获取到的model由于是动态创建的,所以并不会享受到自动创建数据表的待遇。老老实实地手动创建数据表吧。
总结
这里总结下最终的实现方法。
- 修改model的代码。
- 手动创建数据表。你要是不想手动创建,也可以写个方法在第一次进行分表查询或插入时,调用方法进行自动创建对应的数据表。
本文记录了在Django中根据应用名实现动态分表的思路和具体实现过程。通过动态设定Meta类属性,创建新类以操作对应应用名的数据库表。然而,由于动态创建的Model不享受自动建表的待遇,需要手动创建数据表或在首次操作时自动创建。
154

被折叠的 条评论
为什么被折叠?



