Programmatically saving image to Django ImageField
I have some code that fetches an image off the web and stores it in a model. The important bits are:
from django.core.files import File # you need this somewhere
import urllib
# The following actually resides in a method of my model
result = urllib.urlretrieve(image_url) # image_url is a URL to an image
# self.photo is the ImageField
self.photo.save(
os.path.basename(self.url),
File(open(result[0], 'rb'))
)
self.save()
That's a bit confusing because it's pulled out of my model and a bit out of context, but the important parts are:
- The image pulled from the web is not stored in the upload_to folder, it is instead stored as a tempfile by urllib.urlretrieve() and later discarded.
- The ImageField.save() method takes a filename (the os.path.basename bit) and a django.core.files.File object.
Let me know if you have questions or need clarification.
Edit: for the sake of clarity, here is the model (minus any required import statements):
class CachedImage(models.Model):
url = models.CharField(max_length=255, unique=True)
photo = models.ImageField(upload_to=photo_path, blank=True)
def cache(self):
"""Store image locally if we have a URL"""
if self.url and not self.photo:
result = urllib.urlretrieve(self.url)
self.photo.save(
os.path.basename(self.url),
File(open(result[0], 'rb'))
)
self.save()
Django image saving
you can do it in the following way
I'll put the functions here, but you can put them in another file to reuse them and then import them, I'll add the necessary libraries
import PIL
from io import BytesIO
from PIL import Image
from django.core.files import File
class Image(models.Model):
image = models.FileField()
def save(self, *args, **kwargs):
new_image = self.compress_images(self.image)
# asignar la nueva imagen con menor peso
self.image = new_image
super().save(*args, **kwargs)
def valid_extension(self,_img):
if '.jpg' in _img:
return "JPEG"
elif '.jpeg' in _img:
return "JPEG"
elif '.png' in _img:
return "PNG"
def compress_images(self,image):
im = Image.open(image)
width, height = im.size
im = im.resize((width-50, height-50), PIL.Image.ANTIALIAS)
# crear a BytesIO object
im_io = BytesIO()
im.save(im_io, self.valid_extension(image.name) ,optimize=True,
quality=70)
new_image = File(im_io, name=image.name)
return new_image
Programmatically saving image to Django ImageField returning 404 in production
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 save an image using django imageField?
Just because you're not using an actual HTML form to submit the data doesn't mean you can't use a ModelForm
to process the request:
from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseNotAllowed
from django.utils import simplejson
def upload_view(request):
if request.method == 'POST':
form = UploadForm(request.POST, request.FILES)
if form.is_valid():
form.save()
result = {'success': True}
return HttpResponse(simplejson.dumps(result), mimetype='application/json')
else:
return HttpResponseBadRequest()
else:
return HttpResponseNotAllowed(['POST'])
Django - Saving an image manually to an ImageField field
I have solved my problem simply by moving:
super(Image, self).save(*args, **kwargs)
to the end of def save(). I'm still not certain why it's happening this way, but my only explanation is that save() itself is persisting fields values to the database and hence it needs to be executed at the very end.
Django ImageField: directly using file from disk
Use uploadedfile
--(Django doc) class as
from django.core.files.uploadedfile import UploadedFile
instance = MyModel(
image=UploadedFile(
file=open("/home/user/path/to/file/foo.jpg", 'rb')
)
)
instance.save()
Result
Save a generated PIL image into an ImageField in django
You can use a BytesIO to save the Pillow file to an in-memory blob. Then create a File
object and pass that to your model instance ImageField's save
method.
from io import BytesIO
from django.core.files import File
canvas = Image.new('RGB', (total_width, total_height), 'white')
...
blob = BytesIO()
canvas.save(blob, 'JPEG')
self.qrcode_file.save('ticket-filename.jpg', File(blob), save=False)
Check out the django documentation for the File
object.
https://docs.djangoproject.com/en/2.0/ref/files/file/#the-file-object
You have to use save=False
, since the default save=True
means that the parent model's save
method would be called after the image is saved. You don't want recursion here, since you would typically end up in an infinite loop.
Programatically saving an image to a Django ImageField is creating an infinite loop of images
I think from a browse through the source code that calling ImageFileField.save()
(actually FileField.save()
due to inheritance) causes the instance (namely the db row) that the file name is stored in to be updated.
This means that in your save
method you call ImageFileField.save()
which in turn calls your save method, causing the recursion.
From reading the source code, if you want to prevent this, then just pass save=False
to self.image.save
. This will save the file data to disk, but just won't save
the instance (db row) data. However in the next line you save it by calling the superclass, so I think it will be saved to the database then.
In fact it looks like that the save=False
on the save
method was designed to help with this case!
Related Topics
What Are the Most Common Python Docstring Formats
How to Manually Install a Pypi Module Without Pip/Easy_Install
Python/Numpy First Occurrence of Subarray
Choosing a File in Python with Simple Dialog
Run a Program from Python, and Have It Continue to Run After the Script Is Killed
Calculating Direction of the Player to Shoot Pygame
How to Get Numbers After Decimal Point
Using Logging in Multiple Modules
What Is the Easiest Way to Remove All Packages Installed by Pip
How to Access the Child Classes of an Object in Django Without Knowing the Name of the Child Class
How to See If There's an Available and Active Network Connection in Python
How Would I Access Variables from One Class to Another