Django关联模型保存前全局校验及原子性保存问题求助
解决方案
要实现保存Model1前批量校验所有关联Model2实例的需求,你可以通过重写Django Admin中ModelAdmin的save_formset方法来实现,具体步骤如下:
1. 定义禁止的特定值
先明确Model2的name字段不允许的取值,比如我们设置禁止值为admin和root。
2. 自定义内联类(若已有可跳过)
如果还没定义Model2的内联类,先创建一个:
from django.contrib import admin from .models import Model1, Model2 class Model2Inline(admin.TabularInline): model = Model2 extra = 0 # 控制默认显示的空白内联数量,可按需调整
3. 重写Model1Admin的save_formset方法
在Model1的Admin类中,重写save_formset钩子,批量校验所有内联的Model2表单:
from django.core.exceptions import ValidationError class Model1Admin(admin.ModelAdmin): inlines = [Model2Inline] # 定义禁止的name值集合 FORBIDDEN_NAMES = {'admin', 'root'} def save_formset(self, request, form, formset, change): # 遍历所有内联表单,批量校验 for inline_form in formset: # 跳过标记为删除的条目 if inline_form.cleaned_data.get('DELETE'): continue # 校验name字段 model2_name = inline_form.cleaned_data.get('name') if model2_name in self.FORBIDDEN_NAMES: raise ValidationError(f"Model2的名称不能为「{model2_name}」") # 所有校验通过后,执行保存操作 super().save_formset(request, form, formset, change)
原理说明
save_formset是Django Admin专门用于处理内联表单集的钩子方法,会在主模型(Model1)和内联模型(Model2)保存前触发。- 遍历表单集时跳过删除操作的条目,避免误校验待删除的数据。
- 只要有一个Model2的name不符合规则,就抛出
ValidationError,此时Django的事务机制会自动回滚所有未提交的操作(包括Model1的修改和Model2的创建),确保数据的原子性。
内容的提问来源于stack exchange,提问作者Jake Mulhern
相关产品推荐
相关产品推荐

