2011-10-25 91 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 

這對我的作品。我認爲你也不會有任何問題:)