How to assign a local file to the FileField in Django?
Asked Answered
D

4

47

I was trying to assign a file from my disk to the FileField, but I have this error:

AttributeError: 'str' object has no attribute 'open'

My python code:

pdfImage = FileSaver()
pdfImage.myfile.save('new', open('mytest.pdf').read())

and my models.py

class FileSaver(models.Model):

    myfile = models.FileField(upload_to="files/")

    class Meta:
        managed=False

Thank you in advance for your help

Dewdrop answered 17/8, 2010 at 10:48 Comment(0)
O
59

Django uses it's own file type (with a sightly enhanced functionality). Anyway Django's file type works like a decorator, so you can simply wrap it around existing file objects to meet the needs of the Django API.

from django.core.files import File

local_file = open('mytest.pdf')
djangofile = File(local_file)
pdfImage.myfile.save('new', djangofile)
local_file.close()

You can of course decorate the file on the fly by writing the following (one line less):

pdfImage.myfile.save('new', File(local_file))
Oscilloscope answered 17/8, 2010 at 12:27 Comment(5)
overwriting <type 'file'> is probably a bad idea. Better to use file_Mise
Just to explain the above comment (I was confused for a bit) Aaron is talking about the symbol file (i.e. the name of the variable) rather than the type of argument passed.Petasus
Remember to close both the python file object, and the Django File object.Exhilaration
If you get a UnicodeDecodeError, try open the file in binary mode: local_file = open("mytest.pdf", "rb").Jaclin
As the "file" variable was renamed to "local_file" in the answer, @AaronMcMillin ' s comment doesn't make sense anymore.Strontianite
A
5

If you don't want to open the file, you can also move the file to the media folder and directly set myfile.name with the relative path to MEDIA_ROOT :

import os
os.rename('mytest.pdf', '/media/files/mytest.pdf')
pdfImage = FileSaver()
pdfImage.myfile.name = '/files/mytest.pdf'
pdfImage.save()
Adsorb answered 11/2, 2021 at 19:2 Comment(0)
L
3

If you want to upload a local file in django, you can do this

from django.core.files import File

file = open(filepath, 'rb')
file_to_upload = File(file, name=f'{your_desired_name}')
file.close()

Now you can pass the file to django rest serializer to upload or whatever your use-case is. If passing this file to serializer, be sure to close it after it has been passed to serializer.

Note: The filepath here can be django's temporary file or any stored file.

Loth answered 9/6, 2022 at 13:38 Comment(0)
F
2

if you are getting error like:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0x89 in position...

then you have to open the file in binary mode: open("mytest.pdf", "rb")

full example:

from django.core.files import File

pdfImage = FileSaver()
pdfImage.myfile.save('new.pdf', File(open('mytest.pdf','rb')))
Florescence answered 2/9, 2021 at 23:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.