| 问题描述
需求的效果是:
- 新建表单,必须上传文件
- 编辑表单时,分以下两种情况:
- 上传新文件,则替换并删除旧文件
- 不上传文件,则保留原文件
实现请求时出现的问题:编辑时,如果不上传新文件,导致无法通过表单验证。
| 解决方法
| models.py
设置“文件上传”字段
#...
class Download(models.Model):
#...
file_upload = models.FileField('可下载文件', upload_to='download/', blank=True)
#...
|** **forms.py
设置文件上传字段表格样式并启用文件类型验证
#...
class DownloadForm(forms.ModelForm):
"""下载文件表单"""
class Meta:
model = Download
fields = ['file_name', 'file_name_en', 'file_upload', 'file_type']
widgets = {
'file_name': forms.TextInput(attrs={'class':'form-control'}),
'file_name_en': forms.TextInput(attrs={'class':'form-control'}),
'file_upload': forms.ClearableFileInput(attrs={'onchange':'check_type(this)'}),
'file_type': forms.Select(attrs={'class':'form-control'}),
}
def clean_file_upload(self):
"""自定义file_upload校验"""
avaliable_ext = ['xls', 'xlsx', 'doc', 'docx', 'cad', 'pdf', 'stp', 'step']
file_upload = self.cleaned_data.get('file_upload')
if not file_upload:
raise forms.ValidationError('必须上传一个文件')
elif file_upload.name.split('.')[-1] not in avaliable_ext:
raise forms.ValidationError('暂不支持该类型文件上传')
else:
return file_upload
|** **views.py
编辑和新建时的逻辑
#...
import os
#...
def file_upload_copy(request, edit_type='new', edit_id=None):
if edit_type == 'edit':
file_info = Download.objects.get(id=edit_id)
file_original_name = file_info.file_upload.name # 需要提前获取好原文件名
if request.method == 'POST':
if edit_type == 'edit':
form = DownloadForm(request.POST, request.FILES, instance=file_info) # 修改时别忘了传入原来的数据
else:
form = DownloadForm(request.POST, request.FILES)
if form.is_valid():
if edit_type == 'edit' and 'file_upload' in form.changed_data:
# 如果文件修改了,删除文件
original_path = os.path.join(settings.BASE_DIR, 'upload/'+file_original_name)
if os.path.exists(original_path):
os.remove(original_path)
form.save()
if edit_type == 'edit':
notification = '修改'
else:
notification = '创建'
request.session['file_upload'] = 'success'
request.session['file_upload_content'] = '可下载文件已%s成功' % notification
return HttpResponseRedirect(reverse('adminlte:file'))
else:
if edit_type == 'edit':
form = DownloadForm(instance=file_info)
else:
form = DownloadForm()
return render(request, 'adminlte/file_upload copy.html', {
'form': form,
'page_title': '可下载文件',
'content_header': '文件上传',
'highlight_nav': 'file_upload',
})
|** **file_upload.html
<div class="form-group">
<label for="{{ form.file_upload.id_for_label }}">上传文件</label>
{{ form.file_upload }}{{ form.file_upload.errors }}
</div>
| 题外话:Django 上传文件大小设置
Django没有限制的情况下,需要调整服务器的限制。
也就是调整 IIS 的上传限制和 Timeout 数值。