How do I set an initial value for a FileField that will display in a ClearableFileInput widget when creating a new object (unbound form)?
I have tried the following but widget.value
does not return a FeildFile
instance if it is the first time the user is creating the object:
models.py
class MyModel(models.Model):
myfile=models.FileField()
forms.py
class MyForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
self.fields['myfile'].initial= 'myfile.pdf'
class Meta:
model = Issuer
fields = ['myfile']
This results in :
Similarly, setting a default value in the modelfield does not work:
class MyModel(models.Model):
myfile=models.FileField(default='myfile.pdf')
The widget initial value is still None
, but if it is left empty and saved the file object myfile.pdf
will be created. The settings.MEDIA_URL
and urls.py
is definitely correct and the file is on the system because it is loaded after form save.
What I am missing is showing it as an initial value before a form is saved and an object created.
This answer suggests you can't provide initial data but you can provide an initial value with a url
attribute to fake the appearance of a file. It's not clear how you would do this though.
Trying to create an initial file object in the form also returns widget.value = None
class MyForm(forms.ModelForm):
f_path = os.path.join(settings.BASE_DIR + settings.MEDIA_URL, 'myfile.pdf')
f = open(f_path)
myfile = File(f)
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
self.fields['privacy_policy'].initial = self.myfile
Your last block of code is quite close.
You are actually telling the user through the ClearableFileInput
widget that if the user does not input anything in the file input, the initial value will be your pdf file.
But, this is only for display, you have to actually put the logic when you save the instance! (FileField won't do it for you) So the right thing is to override the save()
method of your form, and in the case of a creation, put the actual file as the value. Like this:
class MyForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
path = os.path.join(settings.MEDIA_ROOT, 'myfile.pdf')
self.default_file = open(path)
super(MyForm, self).__init__(*args, **kwargs)
self.fields['privacy_policy'].initial = File(self.default_file)
self.fields['privacy_policy'].initial.url = default_storage.url('myfile.pdf')
def save(self, commit=True):
# Actually put the default file as a value if no input for creation
if not self.instance.pk and not self.cleaned_data.get('privacy_policy'):
self.instance.privacy_policy = self.default_file
self.instance.privacy_policy._committed = True
super().save(commit)
You can't. The only way to set the value of a file input is by the user to select it. This is done for security reasons. Otherwise, you would be able to create a Javascript that automatically uploads a specific file from the client's computer. it has nothing to with Django (model, form) its a browser feature, we only do the things with Django form if it is possible in Html and javascript.
your form:
class MyForm(forms.ModelForm):
f_path = os.path.join(settings.BASE_DIR + settings.MEDIA_URL, 'myfile.pdf')
f = open(f_path)
myfile = File(f)
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
self.fields['privacy_policy'].value = self.myfile
the default ClearableFileField template is
{% if widget.is_initial %}{{ widget.initial_text }}: <a href="{{ widget.value.url }}">{{ widget.value }}</a>{% if not widget.required %}
<input type="checkbox" name="{{ widget.checkbox_name }}" id="{{ widget.checkbox_id }}">
<label for="{{ widget.checkbox_id }}">{{ widget.clear_checkbox_label }}</label>{% endif %}<br>
{{ widget.input_text }}:{% endif %}
<input type="{{ widget.type }}" name="{{ widget.name }}"{% include "django/forms/widgets/attrs.html" %}>
The widget is_initial
should be true to see the link.
class ClearableFileInput(FileInput):
...
def is_initial(self, value):
"""
Return whether value is considered to be initial value.
"""
return bool(value and getattr(value, 'url', False))
....
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With