2011-10-25 22 views
15

消失这是问题所在,我有一个包含Django表单文件领域,即:Django表单文件的字段上的形状误差

photo = forms.FileField(help_text="Please attach a photo", required=False) 

如果表单验证,文件字段是有界的,正确保存。 问题是当用户填写所有表单并且不验证时:所选文件的路径消失

因此,如果用户没有意识到这一点,他/她会修复其他字段错误并再次提交 - 这次没有照片。

以防万一,形式是在这样的视图中创建:

ProfileForm(request.POST or None, request.FILES or None) 

和HTML是:

<div id="uniform-id_photo" class="uploader"> 
    <input id="id_photo" class="clearablefileinput" type="file" name="photo" size="19" style="opacity: 0;"> 
    <span class="filename" style="-moz-user-select: none;">No file selected</span> 
    <span class="action" style="-moz-user-select: none;">Choose File</span> 
</div> 

有没有人有同样的问题?任何想法的解决方案? :)

谢谢!

+0

如果你看看django的管理员,每当你提交一个不正确的表单,它就会重置文件路径。我想有没有办法做到这一点,但为什么不突出显示您的HTML文件字段? – iva123

+0

是的,这可能是唤起用户注意的最简单的方法。谢谢! – Sam

回答

26

不幸的是,这是一个由浏览器强加的问题(确实是一个安全特性),并且不可解决。浏览器不会让你指定文件输入的初始值,也没有什么可以解决这个问题的。

原因是,如果一个网站可以做到这一点,它会打开一个向量,允许任何网站通过猜测文件路径来窃取您计算机上的任何文件 - 它们可能只是在后台运行脚本试图发布有趣的文件回服务器。

唯一的解决方法是将上传的文件实际上保存在服务器上,无论表单是否有效,然后当您将表单和错误呈现给用户时,表明您已收到文件,填写该字段以替换它。

+0

我明白了,有道理。感谢您的友好和详细的答案! – Sam

+0

另一个解决方法是执行AJAX请求来验证表单。 –

0

我写了一些解决方案:

class CustomClearableFileInput(ClearableFileInput): 

def render(self, name, value, attrs=None): 
    if len(<YourModel>.objects.filter(id=self.form_instance_id))>0: 
     file = <YourModel>.objects.get(id=self.form_instance_id).<yourField> 
    else: 
     file = '' 
    substitutions = { 
     'initial_text': self.initial_text, 
     'input_text': self.input_text, 
     'clear_template': '', 
     'clear_checkbox_label': self.clear_checkbox_label, 
    } 
    template = '%(input)s' 
    substitutions['input'] = super(ClearableFileInput, self).render(name, value, attrs) 
    self.template_with_initial = ('<p class="file-upload">%s</p>' 
         % self.template_with_initial) 
    self.template_with_clear = ('<span class="clearable-file-input">%s</span>' 
         % self.template_with_clear) 

    if value and hasattr(value, "url"): 
     template = self.template_with_initial 
     substitutions['initial'] = format_html(self.url_markup_template, 
               value.url, 
               force_text(value)) 
     if not self.is_required: 
      checkbox_name = self.clear_checkbox_name(name) 
      checkbox_id = self.clear_checkbox_id(checkbox_name) 
      substitutions['clear_checkbox_name'] = conditional_escape(checkbox_name) 
      substitutions['clear_checkbox_id'] = conditional_escape(checkbox_id) 
      substitutions['clear'] = CheckboxInput().render(checkbox_name, False, attrs={'id': checkbox_id}) 
      substitutions['clear_template'] = self.template_with_clear % substitutions 
      url = '' if file == '' else file.url 
    else: 
     template = self.template_with_initial 

     substitutions['initial'] = format_html(self.url_markup_template, 
               url, 
               force_text(file)) 
     if not self.is_required: 
      checkbox_name = self.clear_checkbox_name(name) 
      checkbox_id = self.clear_checkbox_id(checkbox_name) 
      substitutions['clear_checkbox_name'] = conditional_escape(checkbox_name) 
      substitutions['clear_checkbox_id'] = conditional_escape(checkbox_id) 
      if fav == '': 
       substitutions['clear'] = CheckboxInput().render(checkbox_name, False, attrs={'id': checkbox_id, 'disabled': 'disabled'}) 
      else: 
       substitutions['clear'] = CheckboxInput().render(checkbox_name, False, attrs={'id': checkbox_id}) 
      substitutions['clear_template'] = self.template_with_clear % substitutions 



    return mark_safe(template % substitutions) 

,然后在表格你必须写:

class <YourModel>Form(ModelForm): 
    class Meta: 
     model = <YourModel> 
     fields = '__all__' 
     widgets= {'<YourField>': CustomClearableFileInput} 

    def __init__(self, *args, **kwargs): 
     super(OperatorSettingsForm, self).__init__(*args, **kwargs) 
     self.fields['<YourField>'].widget.form_instance_id = self.instance.id 

这对我的作品。我认为你也不会有任何问题:)