微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

django 动态创建一个模型的多个table name, 并通过 Django ORM 操作

动态创建table, 并通过 Django ORM 操作.

动态的创建表

动态的创建模型其实就是在运行时生成 Model 类, 这个可以通过函数实现, 通过传参(今天的日期,如: 20181211),然后生成新的模型类, Meta 中的 db_table 为log_20181211.

def get_log_model(prefix):
    table_name = 'log_%s' % str(prefix)

    LOG_LEVELS = (
        (0, 'DEBUG'),        (10, 'INFO'),        (20, 'WARNING'),    )

    class LogMetaclass(models.base.ModelBase):
        def __new__(cls, name, bases, attrs):
            name += '_' + prefix  # 这是Model的name.
            return models.base.ModelBase.__new__(cls, attrs)

    class Log(models.Model):
        __Metaclass__ = LogMetaclass
        level = models.IntegerField(choices=LOG_LEVELS)
        msg = models.TextField()
        time = models.DateTimeField(auto_Now=True, auto_Now_add=True)

        @staticmethod
        def is_exists():
            return table_name in connection.introspection.table_names()

        class Meta:
            db_table = table_name

    return Log

可以看到, 通过函数生成不同的 Log Class. 注意LogMetaclass和__Metaclass__,元类可以在运行时改变模型的名字,table 的名称我们可以通过db_table定义,类的名称可以通过覆盖元类方法定义。

print cls.__name__
Log_20181211
print cls._Meta.db_table
log_20181211

使用

使用直接通过函数获取当前日期的 Log 模型, 然后通过is_exists判读表是否创建, 没有创建则创建对应的表.

def index(request):
    today = date.today().strftime("%Y%m%d")

    # RuntimeWarning: Model '__main__.logclasslog_' was already registered.
    # Reloading models is not advised as it can lead to inconsistencies
    # most notably with related models.
    # 如上述警告所述, Django 不建议重复加载 Model 的定义.
    # 作为 demo 可以直接通过get_log_model获取,无视警告.
    # 所以这里先通过 all_models 获取已经注册的 Model,    # 如果获取不到, 再生成新的模型.
    try:
        cls = apps.get_model('__main__', 'Log_%s' % today)
    except LookupError:
        cls = get_log_model(today)

    if not cls.is_exists():
        with connection.schema_editor() as schema_editor:
            schema_editor.create_model(cls)

    log = cls(level=10, msg="Hello")
    log.save()

    return HttpResponse('<h1>%s</h1>' % cls._Meta.db_table)

上面获取 cls 部分, 这里的代码先通过apps的已经注册的 all_models 获取,否则一个模型的第二次执行定义代码就会抛出RuntimeWarning警告,在模型的初始化函数都会注册此模型,最好不要重复注册. 先通过 apps.get_model 获取这个模型, 如果没有获取到则通过get_log_model初始化新的模型. 这样做更加稳妥一点.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐