Updating FilesField() django with S3 - django

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/

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

Get image src and alt attribute in Sitecore 6?

I use the following to get, for instance, the header of the current page;
Header = Sitecore.Context.Item["Header"]
But how would i go about getting the src url of a image field?
PictureSrc = Sitecore.Context.Item["MyImage"]
You will want to look at leveraging the Sitecore.Resources.Media.MediaManager to get the URL to a media library item.
Before you get there, get the field from the item and cast it to a FileField. Once you have a FileField you can get access to the MediaItem.
Item item = Sitecore.Context.Item;
Sitecore.Data.Fields.ImageField imgField = ((Sitecore.Data.Fields.ImageField)item.Fields["MyImage"]);
string url = Sitecore.Resources.Media.MediaManager.GetMediaUrl(imgField.MediaItem);
string altText = imgField.Alt;
Link to Sitecore Media Item

How would you tell Django to return ImageField.url (not relative path) when serializing a model?

ImageField on the model
some_image = models.ImageField(upload_to= get_upload_path)
This is what i use for serializing:
data = serializers.serialize("json",ModelName.objects.all(),use_natural_keys=True)
the json i get for some_image is relative to the MEDIA_URL
to solve it manualy i call some_image.url, and that works fine, how do i make it so this will be the default value that the image returns when using serializers.serialize
Here are the docs for specifying which fields get serialized: https://docs.djangoproject.com/en/dev/topics/serialization/#subset-of-fields
It sounds like you should include url and all the other fields except some_image.
I was trying to find a proper solution too. But eventually came up with following code:
stores = list(Store.objects.all().values('title', 'logo'))
for store in stores:
store['logo'] = \
request.build_absolute_uri(settings.MEDIA_URL+store['logo'])
stores_json = json.dumps(stores)