Django-Admin中save_model()错误处理与文件校验实现方案咨询
实现方案说明
你当前的写法存在逻辑问题:先调用super().save_model()再做校验,此时对象已经写入数据库,就算抛出错误也无法回滚已保存的数据,完全不符合「保存前处理」的要求,可按照以下逻辑调整:
校验逻辑优先放在clean()方法
校验逻辑和业务处理逻辑拆分,通用校验(不管是Admin入口还是其他接口入口都要生效的规则)直接写在模型层的clean()方法中,校验不通过时抛出ValidationError,Django会自动拦截后续保存流程,把错误信息返回到前端表单页:
from django.db import models from django.core.exceptions import ValidationError import zipfile class YourModel(models.Model): file = models.FileField(upload_to="uploads/") # 其余自定义字段... def clean(self): super().clean() # 仅当文件字段变更时执行校验 if self.pk is None or "file" in [f.attname for f in self.get_dirty_fields()]: # 校验文件后缀 if not self.file.name.lower().endswith(".zip"): raise ValidationError("仅支持上传zip格式文件") # 校验zip文件合法性 try: with zipfile.ZipFile(self.file, "r") as zf: if zf.testzip() is not None: raise ValidationError("zip文件已损坏") except zipfile.BadZipFile: raise ValidationError("上传的文件不是合法zip包")
如果仅需要在Admin场景下做校验,也可以重写Admin对应表单的clean_file()方法,单独针对file字段做校验。
文件处理逻辑放在save_model(),调整执行顺序
把父类保存方法的调用放到所有处理逻辑之后,先完成校验、解压等操作再执行最终入库:
from django.contrib import admin from .models import YourModel import zipfile import os class YourModelAdmin(admin.ModelAdmin): def save_model(self, request, obj, form, change): if "file" in form.changed_data: # 此处写zip解压、后续业务处理逻辑,clean已经提前保证了文件合法性 extract_path = f"你的解压目录/{obj.id}" os.makedirs(extract_path, exist_ok=True) try: with zipfile.ZipFile(obj.file.path, "r") as zf: zf.extractall(extract_path) # 可补充其他业务逻辑,比如读取解压文件更新模型其他字段 except Exception as e: # 捕获解压阶段的异常,抛出ValidationError即可中断保存 raise ValidationError(f"文件处理失败:{str(e)}") # 所有逻辑处理完成后再执行保存 super().save_model(request, obj, form, change)
内容的提问来源于stack exchange,提问作者xtlc
相关产品推荐
相关产品推荐

