Django文件上传:文件名未保存
我正在上传文件,并把一些信息存储在数据库里。其中一部分信息就是文件名。但是,不知道为什么,文件名似乎没有被保存下来!我会把我认为相关的代码部分贴出来,尽量简短。
class UploadFile(models.Model):
...
theFile = models.FileField(upload_to = "Genius/Uploads/", null = True)
filename = models.CharField(max_length = 50, blank = True, null = False)
class UploadFileForm(ModelForm):
class Meta:
model = UploadFile
fields = ('title', 'theFile', 'date_uploaded',) # Don't prompt for filename
def files_upload(request):
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
form.filename = request.FILES['theFile'].name # TODO: sanitize!
# form.filename = 'foo'
form.save()
return HttpResponseRedirect('/files/upload/successful/')
else:
form = UploadFileForm()
return render_to_response('files/upload_file.html', { 'form': form })
我在保存表单之前和之后检查过request.FILES['theFile'].name的值。出于某种原因,它的值是完整的,但就是没有存进数据库里。
3 个回答
0
我想补充一点,以后你可以尽量避免在模型表单中放置这样的业务逻辑。虽然WoLpH的回答是正确的,并且很好地展示了如何通过ModelForm
处理额外的模型实例,但在某些情况下,字段之间的数据依赖关系应该通过Model
、Form
和ModelForm
的各自clean()
方法来处理,这在官方文档的多个地方都有提到(这里有一篇关于表单的说明,Model
和ModelForm
的API也是一样的)。
在你的情况下,这意味着:
import os
class UploadFile(models.Model):
# ...
def clean(self):
# Field data has already been populated by this point.
# Note that `FieldFile` inherits from `File` and that
# `File.name` is actually the full path to the file
# so we need to get the base path component sans the extension
path, extension = os.path.splitext(self.thefile.file.name)
self.filename = os.path.basename(path)
就这样!如果你正确设置了模型字段的editable
属性,你会发现可以依赖Django自动为UploadFile
模型生成ModelForm
。这意味着你不需要为通用的创建、更新视图或模型的ModelAdmin
定义ModelForm
,这样可以减少需要管理的代码行数!
一般来说,建议你在覆盖默认行为时多考虑一下,是否真的有必要,尤其是在处理业务逻辑的最末端,否则你可能会遭遇意想不到的问题。
1
表单字段的值不是通过表单的属性来访问的。所以,设置 'form.filename' 并不会把值放到 filename 这个字段里。正确的方法是,在调用 form.save() 后,直接在返回的实例上设置这个值。
upload_file = form.save(commit=False)
upload_file.filename = filename
upload_file.save()
2
这是因为 form.filename
是表单中的一个字段,而不是它将要保存的值。
你需要找的是这样的东西:
class UploadFileForm(ModelForm):
def save(self, commit=True):
instance = ModelForm.save(self, commit=False)
instance.filename = self.files['theFile'].name
if commit:
instance.save()
return instance
class Meta:
model = UploadFile
fields = ('title', 'theFile', 'date_uploaded',) # Don't prompt for filename
另一种解决方案:
upload_file = form.save(commit=False)
upload_file.filename = request.FILES['theFile'].name
upload_file.save()