Issue
I would like to create additional tables when I call model.save()
(INSERT
). But I keep getting this error:
django.db.transaction.TransactionManagementError: Executing DDL statements while in a transaction on databases that can't perform a rollback is prohibited.
I tried to create additional tables inside model.save()
and using a pre_save()
signal, I get the same error.
This is a pre_save
solution attempt:
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)
Stack: Django, MySQL.
What I want to implement is to create additional tables for the instance that is being inserted.
To clarify how the miscellaneous per-instance tables are generated, this is the code to derive a per-instance table. For example, for every inserted car instance, there are to be generated miscellaneous Tag tables with sensor measurements:
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
I think that the probable solution is to use "nonatomic" somewhere in the code.
Solution
Temporarily set 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
Using a context manager:
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
Answered By - aaron
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.