2011-01-29 109 views
2

我上传文件并将数据存储在数据库中。部分元数据是文件名称本身。然而,在某个地方,文件名似乎没有得到保存!我只会粘贴我认为是代码相关部分的内容,以保持简短。保存表单后&前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']的值。名称。无论出于何种原因,它是完整的,但似乎从未将其纳入数据库。

+0

只是一个旁注:一些浏览器只发送文件名,其他浏览器发送给你整个路径。 – CodesInChaos 2011-01-29 23:47:27

回答

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() 
+0

哦。所以upload_file变成了实例.. err等待。我很困惑。你能进一步阐述一下吗? Noob在这里。 – Harv 2011-01-30 00:03:44

1

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

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

我只是想补充一点,在未来,您可能会尝试避免将这种业务逻辑放在模型表单上。虽然WoLpH's的答案是正确的,如何通过ModelForm处理额外的模型实例处理,其依赖于数据在ModelFormModelForm API通过他们的尊敬clean()方法处理,并在几个被提到的其他领域领域的特定情况下,一个很好的例子放置在官方参考文档中(这里是forms之一,尽管对于ModelModelForm 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,这就是更少的代码管理!

一般的经验法则是,您会重新考虑重写默认行为是否有理由或独立,特别是当您在业务逻辑链的最远端工作时,否则您可能会感觉到意外触发器的愤怒。