Mini HOWTO: Programmatically upload a file in Django
Surprisely, there is no any good advice in the Internet how to programmatically upload a file to the FileField field in the Django. I want to cover this issue with the sample that shows how to upload a generic file from the Internet to a Django application. The code is simple:
import urllib, mimetypes, os from django.core.files.base import ContentFile #... filename, msg = urllib.urlretrieve(img) ext = mimetypes.guess_extension(msg.type) name, original_ext = os.path.splitext(filename) new_filename = filename if ext != original_ext: new_filename += ext obj.file.save(new_filename, ContentFile(open(filename).read()))
First of all, we retrieves a file. urlretrieve returns a tuple <filename, msg>. filename is a name of a temporary file with the downloaded content. msg is a HTTPMessage class instance that contains headers of the file.
We use msg to determinate the type of the file. For this guess_extension method is used. It is required for the case when the file is generated automatically on the server side (for that case the file will be downloaded without any extension).
After that we compares extensions and generates required new_filename. I want to notice that although a file can be downloaded with the some extension, this extension can be wrong, and only MIME type of the file is a right way to determinate the file's content.
And last step is storing the file in the Django model instance (in our case - obj.file field). Please notice that ContentFile class is used for storing the file - Django requires a chunked file to be uploaded to the FileField field. ContentFile creates a chunked file from the bytes received in the constructor.
Though you can use just certain OS operations to generate a filename and save a file in the required MEDIA_ROOT directory, it is not an easy way (especially if a file field has a non-trivial upload_to attribute value like some lambda). And this is the only way to save a file in a custom file storage.