Python Django记录锁定和原子事务
我试图在我正在做的项目中实现一些关键的更新。 总之,我需要从一个工作文件中获取信息,该文件进行进一步处理,然后将其更新为最终文件。此信息来自不同的来源,因此最好在中间文件上执行此操作,然后将其写入最终文件 我的问题是,一些详图线数据在途中丢失。我在下面的文件中复制了这个问题,以消除任何积垢。只需在manage.py shell中运行这些函数。这在Mariadb和Postgresql中都有体现 有没有更好的方法来实现这一点而不是解决办法 models.py:Python Django记录锁定和原子事务,python,django,postgresql,mariadb,Python,Django,Postgresql,Mariadb,我试图在我正在做的项目中实现一些关键的更新。 总之,我需要从一个工作文件中获取信息,该文件进行进一步处理,然后将其更新为最终文件。此信息来自不同的来源,因此最好在中间文件上执行此操作,然后将其写入最终文件 我的问题是,一些详图线数据在途中丢失。我在下面的文件中复制了这个问题,以消除任何积垢。只需在manage.py shell中运行这些函数。这在Mariadb和Postgresql中都有体现 有没有更好的方法来实现这一点而不是解决办法 models.py: import random from
import random
from decimal import Decimal
from django.db import models, transaction
class Head(models.Model):
name = models.CharField(max_length=20, default="")
h1_text = models.CharField(max_length=20, default="")
def update(self):
tmp1 = Tmp1Head()
tmp1.name = self.h1_text
tmp1.save()
for line in self.head_lines.all():
tl1 = Tmp1Line()
tl1.head = tmp1
tl1.data_text = line.data_text
tl1.t1_data = line.t1_data
tl1.t2_data = Decimal(random.random())
tl1.save()
with transaction.atomic():
transaction.on_commit(tmp1.update)
tmp1.delete() # All fine - remove this work transaction.
return True
class Line(models.Model):
head = models.ForeignKey(Head, on_delete=models.CASCADE, related_name='head_lines')
data_text = models.CharField(max_length=20, default="")
t1_data = models.DecimalField(max_digits=12, decimal_places=2)
class Tmp1Head(models.Model):
name = models.CharField(max_length=20, default="")
def update(self):
tmp2 = Tmp2Head()
tmp2.name = self.name
tmp2.save()
for line in self.tmp1_lines.all():
tl2 = Tmp2Line()
tl2.head = tmp2
tl2.data_summary = line.data_text
tl2.final_data = line.t1_data * line.t2_data
tl2.save()
class Tmp1Line(models.Model):
head = models.ForeignKey(Tmp1Head, on_delete=models.CASCADE, related_name='tmp1_lines')
data_text = models.CharField(max_length=20, default="")
t1_data = models.DecimalField(max_digits=12, decimal_places=2)
t2_data = models.DecimalField(max_digits=12, decimal_places=2)
class Tmp2Head(models.Model):
name = models.CharField(max_length=20, default="")
class Tmp2Line(models.Model):
head = models.ForeignKey(Tmp2Head, on_delete=models.CASCADE, related_name='tmp2_lines')
data_summary = models.CharField(max_length=20, default="")
final_data = models.DecimalField(max_digits=12, decimal_places=2)
# with transaction.atomic():
# transaction.on_commit(tmp1.update)
tmp1.update()
视图.py
from .models import *
def populate():
Head.objects.all().delete()
Tmp1Head.objects.all().delete()
Tmp2Head.objects.all().delete()
head = Head.objects.create(name="test", h1_text="test text")
for tmp in range(1, 5):
Line.objects.create(head=head,
data_text=f"data line:{tmp}",
t1_data=tmp)
def test1(): # all fine but no locking.
batch = Head.objects.first()
batch.update()
def test2(): # record locking but the data lines get lost in the final table.
with transaction.atomic():
batch = Head.objects.select_for_update().first()
batch.update()
def test3(): # record locking, no data lost, but the temp data is not removed.
"""
Same as test 2 but remove the below line from update function in the Head model.
tmp1.delete() # All fine - remove this work transaction.
"""
with transaction.atomic():
batch = Head.objects.select_for_update().first()
batch.update()
为了解决这个问题,我去掉了保存点,现在一切似乎都好了。 它应该是安全的,因为只有程序才能访问临时文件 我将其从models.py中删除:
import random
from decimal import Decimal
from django.db import models, transaction
class Head(models.Model):
name = models.CharField(max_length=20, default="")
h1_text = models.CharField(max_length=20, default="")
def update(self):
tmp1 = Tmp1Head()
tmp1.name = self.h1_text
tmp1.save()
for line in self.head_lines.all():
tl1 = Tmp1Line()
tl1.head = tmp1
tl1.data_text = line.data_text
tl1.t1_data = line.t1_data
tl1.t2_data = Decimal(random.random())
tl1.save()
with transaction.atomic():
transaction.on_commit(tmp1.update)
tmp1.delete() # All fine - remove this work transaction.
return True
class Line(models.Model):
head = models.ForeignKey(Head, on_delete=models.CASCADE, related_name='head_lines')
data_text = models.CharField(max_length=20, default="")
t1_data = models.DecimalField(max_digits=12, decimal_places=2)
class Tmp1Head(models.Model):
name = models.CharField(max_length=20, default="")
def update(self):
tmp2 = Tmp2Head()
tmp2.name = self.name
tmp2.save()
for line in self.tmp1_lines.all():
tl2 = Tmp2Line()
tl2.head = tmp2
tl2.data_summary = line.data_text
tl2.final_data = line.t1_data * line.t2_data
tl2.save()
class Tmp1Line(models.Model):
head = models.ForeignKey(Tmp1Head, on_delete=models.CASCADE, related_name='tmp1_lines')
data_text = models.CharField(max_length=20, default="")
t1_data = models.DecimalField(max_digits=12, decimal_places=2)
t2_data = models.DecimalField(max_digits=12, decimal_places=2)
class Tmp2Head(models.Model):
name = models.CharField(max_length=20, default="")
class Tmp2Line(models.Model):
head = models.ForeignKey(Tmp2Head, on_delete=models.CASCADE, related_name='tmp2_lines')
data_summary = models.CharField(max_length=20, default="")
final_data = models.DecimalField(max_digits=12, decimal_places=2)
# with transaction.atomic():
# transaction.on_commit(tmp1.update)
tmp1.update()