Django模型clean函数抛出ValidationError后FileField文件丢失求助
解决Django Admin验证失败后保留已上传文件的问题
Django Admin默认在表单验证失败时不会保留已上传的文件——临时上传的文件会在请求结束后被清理,而普通字段的POST数据会自动回显。要实现验证失败时保留已上传文件,可以通过自定义ModelForm和ModelAdmin,结合临时存储与session的方式实现。
实现步骤
1. 自定义ModelForm
在表单初始化时从session读取之前保存的临时文件路径,回显到FileField:
from django import forms from .models import License class LicenseForm(forms.ModelForm): class Meta: model = License fields = "__all__" def __init__(self, *args, **kwargs): self.request = kwargs.pop("request", None) super().__init__(*args, **kwargs) # 若为POST请求且session中存在临时文件,设置初始值 if self.request and self.request.method == "POST": file_field_name = "your_file_field" # 替换为你的FileField字段名 temp_file_path = self.request.session.get(file_field_name) if temp_file_path: from django.core.files.storage import default_storage if default_storage.exists(temp_file_path): self.fields[file_field_name].initial = temp_file_path
2. 自定义ModelAdmin
重写changeform_view方法,在验证失败前保存上传的临时文件到存储和session,验证成功后清理临时文件:
from django.contrib import admin from django.core.files.storage import default_storage from .models import License from .forms import LicenseForm class LicenseAdmin(admin.ModelAdmin): form = LicenseForm def get_form(self, request, obj=None, **kwargs): # 把request传递给表单 kwargs["request"] = request return super().get_form(request, obj, **kwargs) def changeform_view(self, request, object_id=None, form_url="", extra_context=None): file_field_name = "your_file_field" # 替换为你的FileField字段名 if request.method == "POST": # 保存上传的文件到临时存储 if file_field_name in request.FILES: uploaded_file = request.FILES[file_field_name] temp_path = default_storage.save(f"temp_uploads/{uploaded_file.name}", uploaded_file) request.session[file_field_name] = temp_path # 验证表单 form = self.get_form(request)( request.POST, request.FILES, instance=self.get_object(request, object_id) ) if form.is_valid(): # 验证成功,清除session中的临时文件路径并删除文件 if file_field_name in request.session: temp_path = request.session.pop(file_field_name) if default_storage.exists(temp_path): default_storage.delete(temp_path) return super().changeform_view(request, object_id, form_url, extra_context)
注意事项
- 替换代码中
your_file_field为你实际的FileField字段名称 - 临时存储目录
temp_uploads需要提前创建,或确保Django使用的存储后端支持自动创建目录 - 需定期清理临时文件,可通过定时任务(如Celery、Django Q)删除
temp_uploads目录下的过期文件 - 多文件上传场景需调整代码以支持多个FileField
内容的提问来源于stack exchange,提问作者mohammad
相关产品推荐
相关产品推荐

