Django文件上传:文件名不粘

时间:2011-01-29 23:30:14

标签: python django file upload

我正在上传文件并在db中存储元数据。部分元数据是文件名本身。然而,在某个地方,文件名似乎没有被保存!我将仅粘贴我认为是代码的相关部分以保持简短。

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']的名字。之前和之前的名字保存表格后。无论出于何种原因,它都是完整的,但似乎永远不会进入数据库。

3 个答案:

答案 0 :(得分: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()

答案 1 :(得分:1)

不能通过表单上的属性访问表单字段值。因此,设置'form.filename'不会将值保存在文件名字段中。而是在form.save()返回的实例上设置值。

upload_file = form.save(commit=False) 
upload_file.filename = filename
upload_file.save() 

答案 2 :(得分:0)

我只想补充一点,将来,您可能会尝试避免在模型表单上放置此类业务逻辑。虽然WoLpH's答案是正确的,并且是如何通过ModelForm处理其他模型实例处理的一个很好的示例,但在Model,{{Form处理具有依赖于其他字段数据的字段的特殊情况。 1}}和ModelForm API通过他们尊重的clean()方法在官方参考文档的几个地方提到(这里是forms上的一个,尽管同样适用于{{1} }和Model API)。

在你的情况下,这意味着:

ModelForm

就是这样!如果您在模型字段上正确设置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) 属性,您会发现可以依靠Django为editable模型自动生成ModelForm。这意味着您不必为通用创建,更新视图或模型的UploadFile定义ModelForm,而且需要管理的代码行更少!

一般的经验法则是,您是否会考虑重写默认行为是否合理或自包含,尤其是当您在业务逻辑链的远端工作时,否则您可能会感受到意外失败的愤怒。