6
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
Oleg Tarasenko
  • 9,324
  • 18
  • 73
  • 102

3 Answers3

8

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.

okm
  • 23,575
  • 5
  • 83
  • 90
6

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)
Community
  • 1
  • 1
ohrstrom
  • 2,890
  • 2
  • 20
  • 34
2

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)
Ryu_hayabusa
  • 3,666
  • 2
  • 29
  • 32