Django Form File Field disappears on form error Django Form File Field disappears on form error django django

Django Form File Field disappears on form error


Unfortunately, this is a problem (really a security feature) imposed by browsers, and is not solvable, as such. Browsers will not let you specify an initial value for file inputs, and there's nothing that you will be able to do to work around that.

The reason is that if a website could do this, it would open up a vector that would allow any website to steal any file on your computer by guessing file paths--they could just have a script running in the background that tried to post interesting files back to the server.

The only workaround is to actually save the uploaded file on the server regardless of whether the form validates, and then when you render the form and errors back to the user, indicate that you have received a file and that they should only fill out that field to replace it.


I write some solution:

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)

And then in your form you must write:

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

It works for me. I think you will have no problem too :)