Seif
Seif

Reputation: 646

How to save an image from Google Places API to an ImageField in a Django app?

I'm building population code to populate Django model 'City' with images from Google Places API.

This is the model:

class City(models.Model):
    city_image = models.ImageField(blank=True, upload_to='city_pictures')

I built the API URL that returns a photo:

#fetch image from this url
        city_image_url = ('https://maps.googleapis.com/maps/api/place/photo'
        '?maxwidth=%s'
        '&photoreference=%s'
        '&key=%s') % (maxwidth, city_image_ref, GoogleKey)

Google says the response is a photo and I tested that on Postman so I want to so something like this:

with urllib.request.urlopen(city_image_url) as response:
            city_image = response
created_city = City.objects.get_or_create(city_id=city_id)[0]
created_city.city_image = city_image 
#plus other fields

But I receive this error:

Traceback (most recent call last): File "C:\Users\bnbih\Djangos\excurj_proj\population_script.py", line 68, in populate() File "C:\Users\bnbih\Djangos\excurj_proj\population_script.py", line 64, in populate created_city.save() File "C:\Users\bnbih\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\models\base.py", line 796, in save force_update=force_update, update_fields=update_fields) File "C:\Users\bnbih\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\models\base.py", line 824, in save_base updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields) File "C:\Users\bnbih\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\models\base.py", line 886, in _save_table for f in non_pks] File "C:\Users\bnbih\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\models\base.py", line 886, in for f in non_pks] File "C:\Users\bnbih\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\models\fields\files.py", line 290, in pre_save if file and not file._committed: AttributeError: 'HTTPResponse' object has no attribute '_committed'

I'm using Python 3 and Django 1.10

Upvotes: 1

Views: 1371

Answers (2)

Seif
Seif

Reputation: 646

After following the above answer and this tutorial

This worked for me to save a Google Places image to an ImageField:

First, prepare the URL to which HTTP Response is an image:

city_image_url = ('https://maps.googleapis.com/maps/api/place/photo'
        '?maxwidth=%s'
        '&photoreference=%s'
        '&key=%s') % (maxwidth, city_image_ref, GoogleKey) 

Second, retrieve that actual image and save it to a variable:

retrieved_image = requests.get(city_image_url)

Third, create a file locally and write the remote image's content to it:

with open(city_names[i] + '.jpg', 'wb') as f:
                f.write(retrieved_image.content)

Fourth, open the file with the image inside it and convert it to a Django File:

reopen = open(city_names[i] + '.jpg', 'rb')
            django_file = File(reopen)

Fifth, create a model object and save the django file inside the ImageField like this:

created_city = City.objects.get_or_create(city_id=city_id)[0]
#save it to the ImageField -> args are: 1. the name of the file that is to be saved in MEDIA_ROOT path 2. The Django file itself 3. save instance
created_city.city_image.save(city_names[i] + '.jpg', django_file, save=True)
created_city.save()

Finally, these are the imports you need:

from django.core.files import File
import requests

Upvotes: 0

Marcin Świerczyna
Marcin Świerczyna

Reputation: 112

Try this:

from django.core.files import File
from django.core.files.temp import NamedTemporaryFile

city_image = NamedTemporaryFile(delete=True)
city_image.write(urllib2.urlopen(url).read())
city_image.flush()

created_city = City.objects.get_or_create(city_id=city_id)[0]
created_city.city_image = city_image 

Upvotes: 2

Related Questions