Can't Upload Image to ImageField through csv file - django

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/")

Related

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).

Updating FilesField() django with S3

I want to update the FileField with new file. All the files are saved on S3.
models.py
class PrescriptionMediaStorage(S3Boto3Storage):
location = settings.AWS_PRESCRIPTION_MEDIA_LOCATION
file_overwrite = True
custom_domain = f'{settings.AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com'
class UploadPrescription(models.Model):
image = models.FileField(storage=PrescriptionMediaStorage())
For createview i used:
prescription_obj = UploadPrescription.objects.create(image=image)
prescription_obj.image = prescription_obj.image.url
prescription_obj.save()
For Updateview i tried this but it's giving error
UploadPrescription.objects.filter(id=prescription_id).update(image=image)
prescription_obj = UploadPrescription.objects.get(id=prescription_id)
prescription_obj.image = prescription_obj.image.url
prescription_obj.save()
when i tried to open the saved url in image field i got below message
<Error>
<Code>NoSuchKey</Code>
<Message>The specified key does not exist.</Message>
<Key>media/prescription/1STUSERS-BANNER.jpg</Key>
<RequestId>5D1396D45DF8E1F7</RequestId>
<HostId>0Chq0gedgy/o8942zo5JEz2Tp4iE6df51v0o5iY6GnNGKH3bOXb1ee9XKupKY5GYCfvankTGXHI=
</HostId>
</Error>
Okay, not sure what you are doing here, buth this is how to properly use an ImageField - try these changes and see if they resolve your issue:
Don't write a url to the image field of your model. Assuming <the_image_file> is a valid image file, all you need is one line:
views.py
# creates and saves an UploadPresecription with the given image:
prescription_obj = UploadPrescription.objects.create(image=<the_image_file>)
To use the image in an <image> div, you can access the url like so:
template.html
<image src="{{prescription_obj.image.url}}" />
To replace the image on the prescription_obj, you can simply do this:
views.py
prescription_obj = UploadPrescription.objects.get(id=<the_id>)
prescription_obj.image = <the_new_image_file>
prescription_obj.save()
Note, depending on your settings, your S3 bucket may retain a version of the old image but it will no longer be associated with the updated prescription_obj.
Read about the ImageField here:
https://docs.djangoproject.com/en/3.1/topics/files/

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

how to convert an InMemoryUploadedFile upload to cloudinary in Django=1.11 using cloudinary.uploader.upload()

I am trying to upload an image file to cloudinary which I have sent from my django template to a function in views.py
The file is in request.FILES['image']
cloudinary.config(
cloud_name="p*****",
api_key="33************",
api_secret="4***-S***_o*********"
)
img_obj = request.FILES['image']
cloudinary_response = cloudinary.uploader.upload(img_obj)
image_url = cloudinary_response['url']
Printing img_obj gives the name of the image (Like : "tree.jpg")
cloudinary upload doc is as follows https://cloudinary.com/documentation/image_upload_api_reference#upload
The type of img_obj is InMemoryUploadedFile. Now is there a way to convert it to base64 or somthing like that so I can upload.
Or any other solution ??
You have a few options:
img_obj.file is the actual file object, so you could try uploading that directly.
Since an InMemoryUploadedFile is a subclass of File, you can also just open(mode='rb') the file, using standard python file io functions.
Or you can try img_obj.file.read()
I would go for the second option:
import base64
with img_obj.open("rb") as image_file:
encoded_string = base64.b64encode(image_file.read())

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)