Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

django: Save image from url inside another model

Tags:

python

django

class Item(models.Model):
    name = models.CharField(max_length = 200)
    image = models.ImageField(upload_to = 'read', blank=True)
    creative_url = models.CharField(max_length = 200)
    description = RichTextField()

    def save(self, *args, **kwargs):
        content = urllib2.urlopen(self.creative_url).read()
        self.image.save("test.jpg", File(content))
        super(Item, self).save(*args, **kwargs)

Gives exception: 'str' object has no attribute 'name'

I was trying to follow this answer (http://stackoverflow.com/questions/1393202/django-add-image-in-an-imagefield-from-image-url) But it did not help to get rid of the exception.


AttributeError at /admin/collection/item/1/ 'str' object has no attribute 'name' Request Method:    POST Request
URL:    http://127.0.0.1:8000/admin/collection/item/1/ Django
Version:    1.2.5 Exception Type:   AttributeError Exception Value:  'str'
object has no attribute 'name' Exception
Location:   D:\FF\django\core\files\base.py in _get_size, line 39 Python
Executable: C:\Python27\python.exe Python Version:  2.7.2 Python
Path:   ['D:\\FF',
'C:\\Python27\\lib\\site-packages\\django_social_auth-0.6.7-py2.7.egg',
'C:\\Python27\\lib\\site-packages\\python_openid-2.2.5-py2.7.egg',
'C:\\Python27\\lib\\site-packages\\oauth2-1.5.211-py2.7.egg',
'C:\\Python27\\lib\\site-packages\\httplib2-0.7.4-py2.7.egg',
'C:\\Python27\\lib\\site-packages\\selenium-2.20.0-py2.7.egg',
'C:\\Python27\\lib\\site-packages\\ipython-0.12-py2.7.egg',
'C:\\Python27\\lib\\site-packages\\django_localeurl-1.5-py2.7.egg',
'C:\\Python27\\lib\\site-packages\\pil-1.1.7-py2.7-win32.egg',
'C:\\Python27\\lib\\site-packages\\pip-1.1-py2.7.egg',
'C:\\Windows\\system32\\python27.zip', 'C:\\Python27\\DLLs',
'C:\\Python27\\lib', 'C:\\Python27\\lib\\plat-win',
'C:\\Python27\\lib\\lib-tk', 'C:\\Python27',
'C:\\Python27\\lib\\site-packages',
'c:\\python27\\lib\\site-packages'] Server time:    Tue, 24 Apr 2012
14:19:00 +0300
like image 777
Oleg Tarasenko Avatar asked Apr 24 '12 10:04

Oleg Tarasenko


3 Answers

Instead of File, you need to use django.core.files.base.ContentFile

self.image.save("test.jpg", ContentFile(content), save=False)

File accepts file object or StringIO object having size property or you need to manually set size property of a File or ImageFile to make it working w/ StringIO:

s = StringIO()
s.write(urllib2.urlopen(self.creative_url).read())
s.size = s.tell()
self.image.save('test.jpg', File(s), save=False)

Also, please note the save=False inside self.image.save: by default, save=True, this will cause the instance, which contains the image field, to be saved. Thus the save logic in your code might encounter an infinite loop and reach maximum recursion depth.

like image 81
okm Avatar answered Sep 20 '22 23:09

okm


Try something like:

(As supposed at: Programmatically saving image to Django ImageField)

from django.db import models
from django.core.files.base import ContentFile
import urllib2
from PIL import Image
from StringIO import StringIO

class Item(models.Model):
    name = models.CharField(max_length=200)
    image = models.ImageField(upload_to='read', blank=True)
    creative_url = models.URLField(max_length=200)

    class Meta:
        verbose_name = "Item"
        verbose_name_plural = "Items"

    def download_image(self, url):
        input_file = StringIO(urllib2.urlopen(url).read())
        output_file = StringIO()
        img = Image.open(input_file)
        if img.mode != "RGB":
            img = img.convert("RGB")
        img.save(output_file, "JPEG")
        self.image.save(self.name+".jpg", ContentFile(output_file.getvalue()), save=False)

    def save(self, *args, **kwargs):
        self.download_image(self.creative_url)
        super(Item, self).save(*args, **kwargs)
like image 44
ohrstrom Avatar answered Sep 17 '22 23:09

ohrstrom


solution using requests

from django.core.files.base import ContentFile
from requests import request, HTTPError

def save(self, *args, **kwargs):
    try:
        data = request('GET', self.creative_url,)
        data.raise_for_status()
        self.image.save('fname.jpg', ContentFile(data.content),save=False)
    except HTTPError:
        pass
    super(Item, self).save(*args, **kwargs)
like image 40
Ryu_hayabusa Avatar answered Sep 20 '22 23:09

Ryu_hayabusa