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

Django表单附件保存失败及自定义文件名配置问题求助

问题解决方案

一、表单提交文件无法保存的修复

核心原因

  1. 表单未声明enctype="multipart/form-data",Django无法解析文件上传请求
  2. 表单Widget设置了multiple=True,但模型FileField仅支持单文件上传,导致数据不兼容

修改操作

  1. 更新模板表单标签,添加文件上传必需的编码类型:
<form method="post" enctype="multipart/form-data">
   {% csrf_token %}
   {{form.as_p}}
   <button type="submit">Guardar</button>
   <button type="reset" onclick="return confirmarReset()">Reiniciar</button>
</form>
  1. 移除forms.py中所有ClearableFileInput的multiple=True属性:
# forms.py widgets部分示例修改
'certificado_antecedentes': forms.ClearableFileInput(attrs={'class':'form-control'}),
'hoja_de_vida_conductor': forms.ClearableFileInput(attrs={'class':'form-control'}),
# 其余文件字段均需移除"multiple":True配置

二、实现自定义文件名规则「DSR_--<表单标签>-0-<扩展名>」

核心问题

原upload_directory_name函数无法区分当前上传的是哪个字段,无法获取对应字段的标签文本。需为每个文件字段单独生成带标签的上传处理函数。

修改操作

  1. 在models.py中创建生成上传处理函数的工厂方法:
import os

def generate_upload_handler(field_label):
    def upload_directory_name(instance, filename):
        ext = filename.split('.')[-1]
        # 替换空格为下划线,避免文件名含非法字符
        cleaned_label = field_label.replace(' ', '_')
        cleaned_name = instance.nombre.replace(' ', '_') if instance.nombre else ''
        filename = f"DSR_{instance.rut}-{cleaned_name}-{cleaned_label}-0.{ext}"
        return os.path.join('uploads', filename)
    return upload_directory_name
  1. 为每个文件字段指定带对应标签的上传处理函数:
# models.py 文件字段示例修改
certificado_antecedentes = models.FileField(
    upload_to=generate_upload_handler("Certificado Antecedentes"), 
    null=True, blank=True
)
hoja_de_vida_conductor = models.FileField(
    upload_to=generate_upload_handler("Hoja de vida del conductor"), 
    null=True, blank=True
)
# 其余文件字段均需按此格式,传入forms.py中对应labels的文本

三、实现专属URL上传功能

用户通过邮件接收带自身rut的专属URL(如/candidato_edit/12345678-9/),访问后进入仅能修改自身记录的上传页面。

安全优化(可选)

若需确保用户仅能修改自身记录,在views.py的CandidatoUpdate视图中重写get_object方法:

from django.http import Http404

class CandidatoUpdate(UpdateView):
    model = Candidato    
    form_class = Candidato_form
    template_name = 'candidato/candidato_form.html'
    success_url = '/'  # 替换为实际成功跳转路径

    def get_object(self, queryset=None):
        obj = super().get_object(queryset)
        # 示例:若用户已登录,验证当前用户的rut与记录rut匹配
        # if self.request.user.rut != obj.rut:
        #     raise Http404("无权限修改此记录")
        return obj

专属URL生成示例(后台发送邮件时使用)

from django.urls import reverse
from django.core.mail import send_mail

# 假设candidato是已创建的Candidato实例
upload_url = reverse('candidato_edit', kwargs={'pk': candidato.rut})
full_upload_url = f"http://你的域名{upload_url}"

send_mail(
    "请上传证明文件",
    f"点击链接完成上传:{full_upload_url}",
    "noreply@tuempresa.cl",
    [candidato.correo],
    fail_silently=False,
)

内容的提问来源于stack exchange,提问作者Rikardo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 23:52:57