You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django Admin中是否存在竞态条件?如何预防?

Django Admin 竞态条件相关问题解答

1. Django Admin 是否存在竞态条件?有哪些预防方法?

Django Admin 默认的编辑流程存在竞态条件风险(比如丢失更新、写偏斜)。因为默认逻辑是先从数据库读取对象数据,在页面编辑后提交保存,这个过程中如果有其他用户或请求同时修改同一对象,后提交的更新会覆盖先提交的变更,导致数据丢失。

常见的预防方法包括:

  • 悲观锁(select_for_update()):在读取对象时加行级锁,阻止其他事务修改该对象直到当前事务完成。
  • 乐观锁:给模型添加版本字段(如version = models.IntegerField(default=1)),保存时检查版本号是否匹配,若不匹配则拒绝更新并提示冲突。
  • 事务包裹逻辑:在Admin的保存流程中用事务包裹读取和更新操作,结合锁机制确保原子性。

2. Django Admin 默认是否使用 select_for_update()?如何查看/自定义实现?

Django Admin 默认没有使用select_for_update()来预防竞态条件。你可以查看Django Admin的源码确认:
在django.contrib.admin.options.ModelAdmin类的get_object方法中,默认直接通过模型管理器获取对象,核心代码如下:

def get_object(self, request, object_id, from_field=None):
    queryset = self.get_queryset(request)
    model = queryset.model
    field = model._meta.get_field(from_field or self.pk_name)
    try:
        object_id = field.to_python(object_id)
        return queryset.get(**{field.name: object_id})
    except (model.DoesNotExist, ValueError, TypeError):
        return None

如果要在Admin中实现select_for_update(),可以重写get_object方法,在获取对象时添加锁:

from django.contrib import admin
from .models import YourModel

class YourModelAdmin(admin.ModelAdmin):
    def get_object(self, request, object_id, from_field=None):
        # 添加select_for_update()加行级锁
        queryset = self.get_queryset(request).select_for_update()
        model = queryset.model
        field = model._meta.get_field(from_field or self.pk_name)
        try:
            object_id = field.to_python(object_id)
            return queryset.get(**{field.name: object_id})
        except (model.DoesNotExist, ValueError, TypeError):
            return None

这样进入编辑页面时,会对目标对象加行级锁,直到当前请求的事务完成,避免其他请求同时修改该对象。

注意:Django Admin的默认视图已经包裹了事务,因此上述自定义方法可以直接生效。

内容的提问来源于stack exchange,提问作者Super Kai - Kazuya Ito

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 06:20:53