Max*_*ore 6 django transactions atomic
我有一个简单的任务模型:
class Task(models.Model):
name = models.CharField(max_length=255)
order = models.IntegerField(db_index=True)
Run Code Online (Sandbox Code Playgroud)
还有一个简单的task_create视图:
def task_create(request):
name = request.POST.get('name')
order = request.POST.get('order')
Task.objects.filter(order__gte=order).update(order=F('order') + 1)
new_task = Task.objects.create(name=name, order=order)
return HttpResponse(new_task.id)
Run Code Online (Sandbox Code Playgroud)
视图将新创建的现有任务转移+ 1,然后创建一个新任务.
并且有很多这种方法的用户,我想有一天会因为订购而出错,因为更新和创建肯定应该一起执行.
所以,我只想保持谨慎,这足以避免任何数据损坏:
from django.db import transaction
def task_create(request):
name = request.POST.get('name')
order = request.POST.get('order')
with transaction.atomic():
Task.objects.select_for_update().filter(order__gte=order).update(order=F('order') + 1)
new_task = Task.objects.create(name=name, order=order)
return HttpResponse(new_task.id)
Run Code Online (Sandbox Code Playgroud)
1)可能select_for_update在filter现有的任务创建行中应该做更多的事情Task.objects?
2)return HttpResponse()位于何处?内部交易区块还是外部?
大thx
1)可能在任务创建行中应该做更多的事情,比如
select_for_update在现有过滤之前Task.objects?
不 - 你现在看起来很好,应该按照你想要的方式工作.
2)
return HttpResponse()位于何处?内部交易区块还是外部?
是的,这很重要.无论事务是否成功,您都需要向客户端返回响应 - 因此它肯定需要在事务块之外.如果您在事务内部执行此操作,则如果事务失败,客户端将获得500 Server Error.
但是,如果事务失败,那么您将没有新的任务ID,并且无法在响应中返回该任务ID.因此,您可能需要根据事务是否成功返回不同的响应,例如:
from django.db import IntegrityError, transaction
try:
with transaction.atomic():
Task.objects.select_for_update().filter(order__gte=order).update(
order=F('order') + 1)
new_task = Task.objects.create(name=name, order=order)
except IntegrityError:
# Transaction failed - return a response notifying the client
return HttpResponse('Failed to create task, please try again!')
# If it succeeded, then return a normal response
return HttpResponse(new_task.id)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1536 次 |
| 最近记录: |