Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #AUTOMATIC POSTER DOWNLOADING: original source: http://ishcray.com/downloading-and-saving-image-to-imagefield-in-django
- import imghdr # Used to validate images
- #we will use pillow's copy function rather than the copy module's copy.copy()
- #IMPORTANT: install Pillow instead of PIL. import statement is the same (see Pillow docs)
- from PIL import Image #Holds downloaded image and verifies it
- #imports changed for python3
- import urllib.request # Used to download images (python 2 version: import urllib2)
- import urllib.parse # Cleans up image urls (python 2 version: import urlparse)
- import io # Used to imitate reading from byte file (python 2 version: import cStringIO)
- from django.core.files.base import ContentFile #used to save file. Not included in original guide
- def download_image(url):
- """Downloads an image and makes sure it's verified.
- Returns a PIL (Pillow) Image if the image is valid, otherwise raises an exception.
- """
- headers = {
- 'User-Agent': 'Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0'} # More likely to get a response if server thinks you're a browser
- r = urllib.request.Request(url, headers=headers)
- request = urllib.request.urlopen(r, timeout=10)
- # StringIO (io.BytesIO) imitates a file, needed for verification step
- image_data = io.BytesIO(request.read())
- # Creates an instance of PIL (Pillow) Image class - PIL (Pillow) does the verification of file
- img = Image.open(image_data)
- # Verify the copied image, not original - verification requires you to open the image again after verification, but since we
- # don't have the file saved yet we won't be able to. This is because once we read() urllib2.urlopen we can't access the
- # response again without remaking the request (i.e. downloading the image again). Rather than do that, we duplicate the PIL Image in memory.
- img_copy = img.copy() #uses Pillow's copy instead of the copy.copy()
- if valid_img(img_copy):
- return img
- else:
- # Maybe this is not the best error handling...you might want to just provide a path to a generic image instead
- raise Exception(
- 'An invalid image was detected when attempting to save a Product!')
- def valid_img(img):
- """Verifies that an instance of a PIL Image Class is actually an image and returns either True or False. Note: Copying img returns an instance of the Pillow/PIL Image class, regardless of whether you use copy.copy or Image.copy. So all i'm doing here is checking with pillow's Image.verify() """
- try:
- img.verify()
- return True
- except:
- return False
- else:
- return False
- class Movie(models.Model):
- title = models.CharField(max_length=125)
- release_year = models.IntegerField()
- overview = models.CharField(max_length=325)
- poster_url = models.URLField(max_length=200)
- poster = models.ImageField(upload_to=poster_directory_path, null=True, blank=True)
- def save(self, *args, **kwargs):
- '''I take the url from a field in my Movie model, but feel free to add it back as an argument for the save function'''
- url = self.poster_url
- if self.poster != '' and url != '': # Don't do anything if we don't get passed anything!
- image = download_image(url) # See function definition below
- try:
- filename = urllib.parse.urlparse(url).path.split('/')[-1]
- self.poster = filename
- tempfile = image
- # Will make a file-like object in memory that you can then save
- tempfile_io = io.BytesIO()
- tempfile.save(tempfile_io, format=image.format)
- # Set save=False otherwise you will have a looping save method
- self.poster.save(filename, ContentFile(
- tempfile_io.getvalue()), save=False)
- except Exception as e:
- print("Error trying to save model: saving image failed: " + str(e))
- pass
- # We've gotten the image into the ImageField above...now we actually need to save it. We've redefined the save
- # method for Product (Movie) , so super *should* get the parent of class Product (Movie), models.Model and then run IT'S save
- # method, which will save the Product (Movie) like normal
- super(Movie, self).save(*args, **kwargs)
- def __str__(self):
- return self.title
Advertisement
Add Comment
Please, Sign In to add comment