【问题标题】:Dynamic table creation on a Django Model save在 Django 模型保存上创建动态表
【发布时间】:2021-11-23 09:23:31
【问题描述】:

当我调用model.save() (INSERT) 时,我想创建其他表。但我不断收到此错误:

django.db.transaction.TransactionManagementError: 执行 DDL 在无法执行的数据库事务中的语句 禁止回滚。

我尝试在model.save() 中创建额外的表并使用pre_save() 信号,我得到了同样的错误。

这是pre_save 解决方案尝试:

from django.db import connection
from django.db.models.signals import pre_save
from django.dispatch import receiver


@receiver(pre_save, sender=MyModel, dispatch_uid="create_tags")
def create_tags(sender, instance, **kwargs):
    print("debug, signal pre_save works") 
    try:
        # if obj exists in MyModel table, skip tag table creation
        existing_obj = MyModel.objects.get(name=instance.name)
        print("debug, obj exists")
    except MyModel.DoesNotExist:
        with connection.schema_editor() as schema_editor:
            schema_editor.create_model(MyModel2)

堆栈:Django、MySQL。

我想要实现的是为正在插入的实例创建额外的表。

为了阐明如何生成各种实例表,这是派生实例表的代码。例如,对于每个插入的汽车实例,都会生成带有传感器测量值的杂项标签表:

def get_tag(car_url, car_type):
    class Tag(models.Model):
        time = models.PositiveIntegerField(primary_key=True)  # unix time in seconds  # noqa
        value = models.FloatField()

        class Meta:
            db_table = car_url + "_" + car_type

        def __str__(self) -> str:
            return str(self.time) + "," + str(self.value)

    return Tag

我认为可能的解决方案是在代码中的某处使用“非原子”。

【问题讨论】:

    标签: python mysql django django-models


    【解决方案1】:

    暂时设置schema_editor.connection.in_atomic_block = False

    with connection.schema_editor() as schema_editor:
        in_atomic_block = schema_editor.connection.in_atomic_block
        schema_editor.connection.in_atomic_block = False
        try:
            schema_editor.create_model(MyModel2)
        finally:
            schema_editor.connection.in_atomic_block = in_atomic_block
    

    使用上下文管理器:

    with connection.schema_editor() as schema_editor:
        with non_atomic(schema_editor):
            schema_editor.create_model(MyModel2)
    
    from contextlib import contextmanager
    
    
    @contextmanager
    def non_atomic(schema_editor):
        in_atomic_block = schema_editor.connection.in_atomic_block
        schema_editor.connection.in_atomic_block = False
        try:
            yield
        finally:
            schema_editor.connection.in_atomic_block = in_atomic_block
    

    【讨论】:

      猜你喜欢
      • 2013-01-03
      • 2013-07-07
      • 1970-01-01
      • 2016-10-03
      • 2011-04-12
      • 2013-03-31
      • 1970-01-01
      • 2015-01-22
      • 1970-01-01
      相关资源
      最近更新 更多