specify directory where to store uploaded image - python-2.7

I have a script to save images from request.FILES but I don't know how to specify the directory I want to store it.
photos = request.FILES.getlist('file')
for p in photos:
img = Image.open(p)
img.save(p)
In this case how can I specify the folder I want to store the files? like C:\\upload\\photos\\
EDIT: Alrady try to concatenate the directory path like this:
photos = request.FILES.getlist('file')
for p in photos:
img = Image.open(p)
img.save('C:\\upload\\photos\\'+p)
And gives me this error:
cannot concatenate 'str' and 'TemporaryUploadedFile' objects

I am assuming you use the Pillow module.
If so, construct a full path (path prefix + filename) and pass it to the save function.
Documentation

Related

Can't Upload Image to ImageField through csv file

My Django application:
In my model, I use ImageField to allow the upload of images.
In my csv file I have an image path for an image like this:
C:/Users/blah/DjangoProject/abc/abc/csvs/photos/product_1/product-1_1.jpg
In my csv's view I got:
Product.objects.create(product_name=row[0],
slug=row[0].lower().replace(' ', '-'),
product_description=row[1],
price=row[7],
image_1=ImageFile(open(row[8], 'rb')))
The row[8] contains the image's path.
When I'm going to my csv.html using Django's FileField to upload csv file which contain the image's path and product's info, after uploading the product should be created in my database which image should also be uploaded to a filesystem - not storing in database. Instead, I got this error:
OSError at /csvs/
[WinError 123] The filename, directory name, or volume label syntax is incorrect: 'C:\Users\blah\DjangoProject\abc\abc\media\photos\products\C:'
When I removed the image_1 row in Product.objects.create(), the product was uploaded and added to the database successfully. If I restore the image_1 row in the object creation, I got the same error again.
Does anyone know why?
Try this:
Product.objects.create(product_name=row[0],
slug=row[0].lower().replace(' ', '-'),
product_description=row[1],
price=row[7],
image_1=row[8])
Or
from django.core.files import File;
Product.objects.create(.....,image_1=File(file=open((row[8], 'rb')))
I think you just have to provide the path of the image to be uploaded.
And in your model you have the ImagePath with and upload_to like this:
image_1 = models.ImageField(upload_to="media/styles/")

Get instance by file name for a file in ImageField

Django 3.1.6
class ResponsiveImage(models.Model):
responsive_image = models.ImageField(upload_to=_raster_img_upload_to)
I want to find an instance by the image file_name:
file_name = 'img/raster/0a8449e7-8e50-4c02-853e-59a25592770d/img_144_96_fallback_3x_4.fallback'
ResponsiveImage.objects.get(responsive_image__name=file_name)
But this gets an error:
{FieldError}Unsupported lookup 'name' for ImageField or join on the field not permitted.
Could you help me?
When an ImageField is saved the string for the relative path to the image is stored in the database for your ResponsiveImage object for the field responsive_image.
You should be able to just go
ResponsiveImage.objects.get(responsive_image=file_name)
To get a specific ResponsiveImage object (As long as it actually exists in the database).

Programmatically saving image to Django ImageField returning 404 in production

I have a Django app where users can upload images and can have a processed version of the images if they want. and the processing function returns the path, so my approach was
model2.processed_image = processingfunction( model1.uploaded_image.path)
and as the processing function returns path here's how it looks in my admin view
not like the normally uploaded images
In my machine it worked correctly and I always get a 404 error for the processed ones while the normally uploaded is shown correctly when I try to change the url of the processed from
myurl.com/media/home/ubuntu/Eyelizer/media/path/to/the/image
to
myurl.com/media/path/to/the/image
so how can I fix this ? is there a better approach to saving the images manually to the database ?
I have the same function but returns a Pil.image.image object and I've tried many methods to save it in a model but I didn't know how so I've made the function return a file path.
I think the problem is from nginx where I define the media path.
should/can I override the url attribute of the processedimage?
making something like
model.processed_image.url = media/somefolder/filename
Instead of using the PIL Image directly, create a django.core.files.File.
Example:
from io import BytesIO
from django.core.files import File
img_io = BytesIO() # create a BytesIO object to temporarily save the file in memory
img = processingfunction( model1.uploaded_image.path)
img.save(img_io, 'PNG') # save the PIL image to the BytesIO object
img_file = File(thumb_io, name='some-name.png') # create the File object
# you can use the `name` from `model1.uploaded_image` and use
# that above
# finally, pass the image file to your model field
model2.processed_image = img_file
To avoid repetition of this code, it would be a good idea to keep this code in processingfunction and return the File object directly from there.
My approach is a bit different from #Xyres's, I thought xyres's would make a duplicate of the existing image and create a new one and when I tried overriding the URL attribute it returned an error of
can't set the attribute
but when I saw this question and this ticket I tried making this and it worked
model2.processed_image = processingfunction(model1.uploaded_image.path)
full_path = model2.processed_image.path
model2.processed_image.name = full_path.split('media')[1]
so that explicitly making the URL media/path/to/image and cut out all of the unneeded parts like home/ubuntu and stuff

PIL: saving file in python

from PIL import Image
in_put = raw_input("provide the image path: ")
pic_im = image.open(in_put)
pic_im.rotate(45).show()
pic_im.save("outputfile.jpg")
I use the above code to open and rotate the user input image.
but every time i have to manually change the name of "outputfile.jpg" while saving the image.
Please guide to save the modified image: for example.
if my original file path is E:\Picture\Nature.jpg
then it should save the modified file in save location with name E:\Picture\Nature_modified.jpg
Perhaps something like this?
output_filename = in_put[0:len(in_put)-4] + "_modified.jpg"
pic_im.save(output_filename)

Django upload file into specific directory that depends on the POST URI

I'd like to store uploaded files into a specific directory that depends on the URI of the POST request. Perhaps, I'd also like to rename the file to something fixed (the name of the file input for example) so I have an easy way to grep the file system, etc. and also to avoid possible security problems.
What's the preferred way to do this in Django?
Edit: I should clarify that I'd be interested in possibly doing this as a file upload handler to avoid writing a large file twice to the file system.
Edit2: I suppose one can just 'mv' the tmp file to a new location. That's a cheap operation if on the same file system.
Fixed olooney example. It is working now
#csrf_exempt
def upload_video_file(request):
folder = 'tmp_dir2/' #request.path.replace("/", "_")
uploaded_filename = request.FILES['file'].name
BASE_PATH = '/home/'
# create the folder if it doesn't exist.
try:
os.mkdir(os.path.join(BASE_PATH, folder))
except:
pass
# save the uploaded file inside that folder.
full_filename = os.path.join(BASE_PATH, folder, uploaded_filename)
fout = open(full_filename, 'wb+')
file_content = ContentFile( request.FILES['file'].read() )
try:
# Iterate through the chunks.
for chunk in file_content.chunks():
fout.write(chunk)
fout.close()
html = "<html><body>SAVED</body></html>"
return HttpResponse(html)
except:
html = "<html><body>NOT SAVED</body></html>"
return HttpResponse(html)
Django gives you total control over where (and if) you save files. See: http://docs.djangoproject.com/en/dev/topics/http/file-uploads/
The below example shows how to combine the URL and the name of the uploaded file and write the file out to disk:
def upload(request):
folder = request.path.replace("/", "_")
uploaded_filename = request.FILES['file'].name
# create the folder if it doesn't exist.
try:
os.mkdir(os.path.join(BASE_PATH, folder))
except:
pass
# save the uploaded file inside that folder.
full_filename = os.path.join(BASE_PATH, folder, uploaded_filename)
fout = open(full_filename, 'wb+')
# Iterate through the chunks.
for chunk in fout.chunks():
fout.write(chunk)
fout.close()
Edit: How to do this with a FileUploadHandler? It traced down through the code and it seems like you need to do four things to repurpose the TemporaryFileUploadHandler to save outside of FILE_UPLOAD_TEMP_DIR:
extend TemporaryUploadedFile and override init() to pass through a different directory to NamedTemporaryFile. It can use the try mkdir except for pass I showed above.
extend TemporaryFileUploadHandler and override new_file() to use the above class.
also extend init() to accept the directory where you want the folder to go.
Dynamically add the request handler, passing through a directory determined from the URL:
request.upload_handlers = [ProgressBarUploadHandler(request.path.replace('/', '_')]
While non-trivial, it's still easier than writing a handler from scratch: In particular, you won't have to write a single line of error-prone buffered reading. Steps 3 and 4 are necessary because FileUploadHandlers are not passed request information by default, I believe, so you'll have to tell it separately if you want to use the URL somehow.
I can't really recommend writing a custom FileUploadHandler for this. It's really mixing layers of responsibility. Relative to the speed of uploading a file over the internet, doing a local file copy is insignificant. And if the file's small, Django will just keep it in memory without writing it out to a temp file. I have a bad feeling that you'll get all this working and find you can't even measure the performance difference.