Django FileField upload - django

I am quite confused.
I have wrote an upload form in my site. everything works perfectly..
however, I am reading that I needed to implement a function like handle_uploaded_file to dump the file content from the request.FILES to a physical file.
however , I didn't do it any the file exists in the location I set the upload_to in the FileField field. everything works as expected..
Am I missing something ? why do I need handle_uploaded_file then ?

No, you do not need to do a handle_uploaded_file.
When you save the object (form.save) Django already does this for you.
Look this:
https://github.com/django/django/blob/master/django/db/models/fields/files.py#L270-276

Related

Getting file uploads to work with Django & Cloudinary

I am trying to use Cloudinary as a CDN and am having some trouble getting file uploads to work properly. I have followed their blog posts and website, but am running into a consistent and very annoying error.
I have a model associated with both an image (a cover photo) and a media object (a PDF or ebook, like a .mobi or .epub). I have a model form set up to create an object:
class NewMediaObjectForm(forms.ModelForm):
class Meta:
model = MediaObject
fields = ('cover_photo', ...)
cover_photo = CloudinaryJsFileField(options={'tags': 'cover_photo'})
Now, I've read this tutorial from Cloudinary and I know that their form looks like this:
class NewMediaObjectForm(forms.ModelForm):
class Meta:
model = MediaObject
fields = ('cover_photo', ...)
cover_photo = CloudinaryJsFileField(options={'tags': 'cover_photo'})
Here's my problem: if I match their level of indention, the generated HTML shows that the input field is getting all of the right Cloudinary stuff attached to it - but the upload itself doesn't work. The page simply refreshes with an error message stating that no image was selected. Importantly, I can see from the generated HTML that the tags I've specified are coming through.
If I use method #1, with my indention, the file uploads to Cloudinary but none of my tags are applied. It also treats everything as an image, giving me a "invalid image file" error when trying to upload anything other than images (such as the ebook files I mentioned earlier).
I want both - how can I get this upload field to work AND get it to respect the options I'm trying to define?
(I do have cloudinary.config called in the appropriate views; I do have cloudinary_includes and cloudinary_js_config in the appropriate templates; I've imported everything and am calling cl_init_js_callbacks on the form in the view.)
One more addition - I am running this on a local machine using manage.py's runserver rather than deploying, if that has any impact on the configuration.
UPDATE:
I found something I was doing wrong. I've fixed it and made things worse.
The necessary jQuery was not being loaded. Now I am loading it, but the upload button simply doesn't function. I press the button, I select the file, the select dialog disappears, and it shows that no file has been selected. However, I can see that the tags are being passed to the generated HTML, so it's a step in the right direction. Any ideas?
Please forgive me. This was a PEBCAK issue; I will leave this visible for anyone else who may make the same mistakes I've made in the future.
Make sure the proper jQuery scripts are being loaded - open the Chrome developer console, Firebug, whatever and double check. Then, make sure they're being loaded after the DOM so that there are elements for the script to attach to.
Cloudinary will expect html/cloudinary_cors.htmlto be accessible in your static directory.
Either I have broken something, or the default behavior for this particular type of ModelField is to simply IMMEDIATELY upload the selected file and continue displaying "No File Chosen." I thought that nothing was happening and was very surprised when I saw 50+ images successfully uploaded.

How to upload images to Django media without subdirectory

I need to upload an image to a Django ImageField, but due to a restriction based on a third party API, I need the images to be uploaded to the media directory without a subdirectory.
The restriction is due to the fact that the filename stored locally (in the imagefield column) is used to calculate a hash to request that image from a media API, so the field must contain the same name as the filename in the API, unfortunately the API filename cannot contain slashes.
I can't add a field to the db to store the real filename, nor can I control the code that returns the calculated hash.
I tried making the upload_to a callable that returns an empty string, which seems to get around the upload_to required error, but the images are all then saved as just ''(blank) _1, _2 ... etc without the rest of the image name.
I have also tried making the upload_to return '/', '../media', '../media/' all to no avail (a variety of errors or malformed filenames)
So TL;DR how to save images directly to MEDIA_ROOT, without a sub directory?
EDIT, extra info:
So I just tried a little hack that does part of it:
from django.core.files.storage import FileSystemStorage
media_root_store = FileSystemStorage(location='/path/to/media/parent')
class MyModel(models.Model):
img_file = models.ImageField(
max_length=255,
upload_to='media',
storage=media_root_store)
This dirty hack saves the image to the correct location, though it still obviously saves the image path with media/ appended. So I'm unsure if it has actually gotten me any closer.
Turns out there was a pretty big clue in the error from my earlier attempt (the one generating _1, _2 etc)
If I specify an upload_to callable that simply returns the filename argument, then the image will be saved directly in the MEDIA_ROOT, with the correct filename saved in the database (without the directory prefix).
I had been under the impression that upload_to will just provide a path to append to MEDIA_ROOT, which will then have the image filename appended to that. Turns out this is incorrect.

How does one obtain the type of an uploaded file in Django forms?

I have tried:
self.data['uploaded_file'].content_type
However, this gives an error that says the object lacks a content_type attribute.
Any ideas as to why? Thank you.
What is the best way to verify file type in Django forms?
The content_type attribute is only present on the UploadedFile instances contained in request.FILES; you will need to get the content type from that, or use magic to get it from the raw file data.
How could you tell a file is binary file or text or some other stuff?
Perhaps using the file extension is a way, but not always makes sense.

Django: Saving a file from disk with FileField

In my app I parse some xml which contains a path to an image file. Now if I am passing the path to the property of my model which is a FileField it's not copying the file using the upload_to settings. I also tried to pass it a stream of that file but that raised an exception.
How do I use the FileField with data that isn't coming from a request?
Assuming the file is in your MEDIA_ROOT (If it's outside of MEDIA_ROOT you'll get SuspiciousOperation errors):
m = YourModel(file='uploads/file.txt')
If you already have the file on your system, it'd surely be easier to just move it to your uploads directory. You could always customize FileField to handle moving the file for you.

django file upload in 2 steps

I want to upload a file in 2 steps.
First I want to upload it and show the errors and on the second step I
want actually to save the file data in the database.
So I made a simple form and my problem is how to pass the same file to
the form on the second step?
I mean how to insert request.FILES data in the same form again. Or
maybe there is a better way?
Thanks,
Arshavski Alexander.
First,
Using django's inbuilt File field, you don't store the files in the database, but in the filesystem. You only store the metadata in the database.
Next,
If you want to validate a file input, you can use the standard form validation, where you define the the clean_file_field_name and raise the forms.ValidationError django automatically does the "showing of the page until proper input is provided" for you.
That is the right way of doing it.