FileField: force using TemporaryUploadedFile - django

When uploading a file for a field such as this one:
file = FileField(upload_to='/path/')
Django uses either an InMemoryUploadedFile or a TemporaryUploadedFile. The latter is stored on the disk and its file name can be accessed with the temporary_file_path property. The storage choice depends on the file size.
How can I override this behaviour and always upload as a TemporaryUploadedFile for this model field?
The reason I am asking this is because I need to write a validator that uses an external library that can only take file paths as input, no data streams.

By default the upload handlers are:
[
'django.core.files.uploadhandler.MemoryFileUploadHandler',
'django.core.files.uploadhandler.TemporaryFileUploadHandler',
]
And files smaller than 2.5MB are handled with MemoryFileUploadHandler.
So just say in your settings:
FILE_UPLOAD_HANDLERS = ['django.core.files.uploadhandler.TemporaryFileUploadHandler',]

Related

REST framework's FileField: How can I force using TemporaryUploadedFile

I want to extract and process text from a text document uploaded by the user without actually saving the document. I use Django's REST framework and I want this to happen in the serializer.
I get the document from a FileField. Because the text document is likely to be small, it will be wrapped into InMemoryUploadedFile automatically. However, text-extraction modules (e.g. docx2python) need to open files from paths, not from memory.
How can I turn an InMemoryUploadedFile into a TemporaryUploadedFile, so I can get a path to use? Or how do I force a particular field (without changing the app settings) to always wrap a file in TemporaryUploadedFile?

To use Django FileField or FilePathField?

I'm a bit confused about which field to use. What I need is just a Field that will hold a file (audio and/or another one for an image)
The FileField seems to be specifically for uploading and I think it is a bit of overkill for what I need, I also don't like how it will automatically upload and rename the files to a unique filename (file_FHjgh758.txt) everytime something is uploaded.
The problem I have with the FilePathField is that it seems to require an absolute path, which would obviously be different from dev to production, I got around this by adding this to the model...
import os
class Foo(models.Model):
path = os.path.dirname(os.path.dirname(__file__))
path = os.join(path, 'media')
audio = models.FilePathField(path=path)
I have no idea if this is safe or proper, and there aren't many examples online or in the docs to draw from.
To be clear, I just want to have a field which I can point to a file (audio or image) somewhere in my system. What would be the best way to go about doing this?
If you want to refer to files that are already on your filesystem rather than user uploaded files, then FilePathField is the one that you want.
In this regard a few comments:
Don't point to a path that is inside your app's source tree. That is not safe.
You can use settings or environment variables to handle development vs. production paths, e.g., put a FILE_PATH_FIELD_DIRECTORY setting in your development/production settings files and refer to this setting from your app:
from django.conf import settings
class Foo(models.Model):
audio = models.FilePathField(path=settings.FILE_PATH_FIELD_DIRECTORY)

how to retrieve static file's contents in django view?

I have html files and I want to give the contents of the file to user from a django view.
Basically these files are data files whose internal sturcture is html.
** Edit **
So you want to render them (display them in the browser), or send them for download? Are they templates, or files the users have uploaded?
A: Clients will use the html(and other data as well) and replace certain part of the page with it. (I think how I'll use it is not that important though. We can treat html contents as a data)
Will you know the names of the files in question when you write the software, or will you only know their names at runtime?
A: I currently have a table which has the filepath as a field. ie. The filepath can be changed at runtime
You'll want to leverage the staticfiles storage system.
from django.contrib.staticfiles.storage import staticfiles_storage
file_handle = staticfiles_storage.open(your_filename)
contents = file_handle.read()
the filename (your_filename above) should be the relative path to the static file (not including the STATIC_URL (/static/[this part])
Edit: Finder vs Storage
If you want to find static files stored in app directories (or other configured static finders), you need to use a finder, not the storage to retrieve the file contents. Here's how to do that:
from django.contrib.staticfiles.finders import find
file_path = "relative/path/to/file.extension"
abs_path = find(file_path)
file(abs_path).read()

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 save file

I want to create thumbnails for uploaded images. I know there are some libraries available, but I have very basic needs and I would prefer to do this on my own.
My model goes like this:
from image_tools import resize
class Photo(models.Model):
# some fields
image = models.ImageField(
upload_to='images',
height_field='height',
width_field='width'
)
thumb = models.ImageField(
upload_to='thumbs',
editable=False
)
def save(self):
self.thumb = self.image
resize(self.image.path, self.thumb.path, 50, 40)
super(Photo, self).save()
Here resize() is a simple function I have written which accepts as arguments the original file path and the destination path and the dimensions and stores a thumbnail. The only problem is that the file is not yet on the disk at this moment.
Is there a way to force saving the file itself on its location, so that it will be available to my function?
Please, feel free to suggest better ways to handle this matter. Still I would like to know how to handle files which are not yet saved, whatever the best solution turns out to be.
There are a few ways to do this. One you have the raw image data, you can write it to a file pretty easily (look up django file uploading to see how to save an uploaded file to disk). You can read any file your django process (or apache) has access to, not just in the path of your django instance.
Another thing you can do before saving this is to use PIL to thumbnail the image and save it:
http://effbot.org/imagingbook/image.htm
You can also upload the data to s3 using boto s3, if you want the images hosted on a CDN.
Storing the file directly is not a good idea because you ignore the default file storage (i.e. file system, amazon s3, ...)
Better approach is to use django File class
from django.core.files import File
# Create a Python file object using open() and the with statement
>>> with open('/tmp/hello.world', 'w') as f:
... myfile = File(f)
... myfile.write('Hello World')
Also to delete the file use the default storage class
See link below for more details
https://docs.djangoproject.com/en/1.5/topics/files/