| 问题描述

需求的效果是:

  1. 新建表单,必须上传文件
  2. 编辑表单时,分以下两种情况:
    1. 上传新文件,则替换并删除旧文件
    2. 不上传文件,则保留原文件

实现请求时出现的问题:编辑时,如果不上传新文件,导致无法通过表单验证。

| 解决方法

| models.py

设置“文件上传”字段

  1. #...
  2. class Download(models.Model):
  3. #...
  4. file_upload = models.FileField('可下载文件', upload_to='download/', blank=True)
  5. #...

|** **forms.py

设置文件上传字段表格样式并启用文件类型验证

  1. #...
  2. class DownloadForm(forms.ModelForm):
  3. """下载文件表单"""
  4. class Meta:
  5. model = Download
  6. fields = ['file_name', 'file_name_en', 'file_upload', 'file_type']
  7. widgets = {
  8. 'file_name': forms.TextInput(attrs={'class':'form-control'}),
  9. 'file_name_en': forms.TextInput(attrs={'class':'form-control'}),
  10. 'file_upload': forms.ClearableFileInput(attrs={'onchange':'check_type(this)'}),
  11. 'file_type': forms.Select(attrs={'class':'form-control'}),
  12. }
  13. def clean_file_upload(self):
  14. """自定义file_upload校验"""
  15. avaliable_ext = ['xls', 'xlsx', 'doc', 'docx', 'cad', 'pdf', 'stp', 'step']
  16. file_upload = self.cleaned_data.get('file_upload')
  17. if not file_upload:
  18. raise forms.ValidationError('必须上传一个文件')
  19. elif file_upload.name.split('.')[-1] not in avaliable_ext:
  20. raise forms.ValidationError('暂不支持该类型文件上传')
  21. else:
  22. return file_upload

|** **views.py

编辑和新建时的逻辑

  1. #...
  2. import os
  3. #...
  4. def file_upload_copy(request, edit_type='new', edit_id=None):
  5. if edit_type == 'edit':
  6. file_info = Download.objects.get(id=edit_id)
  7. file_original_name = file_info.file_upload.name # 需要提前获取好原文件名
  8. if request.method == 'POST':
  9. if edit_type == 'edit':
  10. form = DownloadForm(request.POST, request.FILES, instance=file_info) # 修改时别忘了传入原来的数据
  11. else:
  12. form = DownloadForm(request.POST, request.FILES)
  13. if form.is_valid():
  14. if edit_type == 'edit' and 'file_upload' in form.changed_data:
  15. # 如果文件修改了,删除文件
  16. original_path = os.path.join(settings.BASE_DIR, 'upload/'+file_original_name)
  17. if os.path.exists(original_path):
  18. os.remove(original_path)
  19. form.save()
  20. if edit_type == 'edit':
  21. notification = '修改'
  22. else:
  23. notification = '创建'
  24. request.session['file_upload'] = 'success'
  25. request.session['file_upload_content'] = '可下载文件已%s成功' % notification
  26. return HttpResponseRedirect(reverse('adminlte:file'))
  27. else:
  28. if edit_type == 'edit':
  29. form = DownloadForm(instance=file_info)
  30. else:
  31. form = DownloadForm()
  32. return render(request, 'adminlte/file_upload copy.html', {
  33. 'form': form,
  34. 'page_title': '可下载文件',
  35. 'content_header': '文件上传',
  36. 'highlight_nav': 'file_upload',
  37. })

|** **file_upload.html

  1. <div class="form-group">
  2. <label for="{{ form.file_upload.id_for_label }}">上传文件</label>
  3. {{ form.file_upload }}{{ form.file_upload.errors }}
  4. </div>

| 题外话:Django 上传文件大小设置

Django没有限制的情况下,需要调整服务器的限制。
也就是调整 IIS 的上传限制和 Timeout 数值。