Context: I want to take a user uploaded file, attach it to a model, change some properties and then save the object to database.
Here's some relevant code:
models.py
def file_upload_path(instance, filename):
path = os.path.join('uploaded_files', str(uuid4()))
return path
class UploadedFile(models.Model):
file_object = models.FileField(null=False, blank=False,
upload_to=file_upload_path)
def __unicode__(self):
return self.file_object.name
forms.py
class UploadFileForm(forms.ModelForm):
class Meta:
model = UploadedFile
fields = ['file_object']
views.py
def home(request):
...
if form.is_valid():
new_file = form.save(commit=True)
print new_file
...
This code prints exactly what I want, which is the file path after upload_to has been called and the file has been saved to said location (eg. "uploaded_files/b992e44e-6403-4c37-82b4-b3c403d07f79").
Now, with this views.py, things change:
views.py
def home(request):
...
if form.is_valid():
new_file = form.save(commit=False)
print new_file
# new_file_object = FileObject(os.path.abspath(new_file.file_object.url))
# new_file.mime_type = new_file_object.get_mime_type()
...
Instead of the path, I get the original filename (eg. "jnes.exe") so I can't process the file so I can get its mime type, for example, and then update the model and save it do the database.
Any ideas what I'm doing wrong? Thanks.
I do the necessary model edits on the file that's still in memory/temporarily on disk since Django doesn't allow you to directly find a FileField's location until you actually save the new model instance.
forms.py
def save(self, commit=True, *args, **kwargs):
new_model = super(UploadFileForm, self).save(commit=False)
file_object = self.cleaned_data['file_object']
file_info = FileObject(file_object)
new_model.mime_type = file_info.get_mime_type()
new_model.sha256 = file_info.get_sha256()
new_model.md5 = file_info.get_md5()
if commit:
new_model.save()
return new_model
I get the hashes and mime type in FileObject's constructor by reading data from Django's UploadedFile temporary object. (thanks Daniel)
The docs state the following
The file is saved as part of saving the model in the database, so the actual file name used on disk cannot be relied on until after the model has been saved.
So you are not anything wrong. It won't be there until it is committed.
If you want to process the file in someway before saving it. You'll want to access it when its a temporary file. This answer can help you with this alternate way of accessing the file to get mimetype etc.
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