python - Django 记录锁定和原子事务
问题描述
我正在尝试在我正在做的项目中实施一些关键更新。总之,我需要从一个工作文件中获取信息,该文件进行一些进一步的处理,然后将其更新为最终文件。此信息来自不同的来源,因此最好在中间文件上执行,然后将其写入最终文件。
我的问题是一些细节线数据在途中丢失了。我在下面的文件中复制了这个问题以消除任何杂物。只需在 manage.py shell 中运行这些函数。这显示在 Mariadb 和 Postgresql 中。
有没有更好的方法来实现这一点而不是解决方法?
模型.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)
视图.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中删除了这个:
# with transaction.atomic():
# transaction.on_commit(tmp1.update)
tmp1.update()
推荐阅读
- python - Anaconda:ImportError:无法从“PIL”(matplotlib.pyplot)导入名称“_imaging”
- javascript - 从分配给映射对象键的数组中提取数组元素
- spring-boot - ThymeleafView:java.lang.IllegalArgumentException:需要属性“区域设置”
- excel - 如何用公式定义数字数组
- python - 无法更改一列中的分类数据(熊猫、机器学习)
- spring-boot - 如何正确模块化应用程序配置,以便测试(IT、datajpa、...)不会获取所有用于生产的内容
- r - 有没有办法在 R(或 ml3)的 recipes 包中对行(尤其是虚拟变量)进行分组
- powerbi - DAX 中的 IF 条件是在行上创建笛卡尔连接
- windows - 在 AD 中将组从一个用户复制到另一个用户,但一个特定组除外
- java - 如何从我的 Application 类中找出 onActivityResult 的结果?