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)

通过以上可以实现简单的动态分表的操作,至于分库使用数据库路由配置即可。

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值