Django:从图像url中的ImageField添加图像

请原谅我难看的英语;-)

想象一下这个非常简单的模型:

class Photo(models.Model): image = models.ImageField('Label', upload_to='path/') 

我想从图片url创build一个照片(即,不要在djangopipe理站点手动)。

我认为我需要做这样的事情:

 from myapp.models import Photo import urllib img_url = 'http://www.site.com/image.jpg' img = urllib.urlopen(img_url) # Here I need to retrieve the image (as the same way that if I put it in an input from admin site) photo = Photo.objects.create(image=image) 

我希望我能很好的解释这个问题,如果不告诉我的话。

谢谢 :)

编辑:

这可能工作,但我不知道如何将content转换为django文件:

 from urlparse import urlparse import urllib2 from django.core.files import File photo = Photo() img_url = 'http://i.ytimg.com/vi/GPpN5YUNDeI/default.jpg' name = urlparse(img_url).path.split('/')[-1] content = urllib2.urlopen(img_url).read() # problem: content must be an instance of File photo.image.save(name, content, save=True) 

我刚刚为这个问题创build了http://www.djangosnippets.org/snippets/1890/ 。 该代码类似于上面的答案,除了使用urllib2.urlopen之外,因为urllib.urlretrieve默认不执行任何error handling,所以很容易得到404/500页面的内容而不是你需要的内容。 你可以创buildcallback函数和自定义的URLOpener子类,但是我发现它更容易创build我自己的临时文件,如下所示:

 from django.core.files import File from django.core.files.temp import NamedTemporaryFile img_temp = NamedTemporaryFile(delete=True) img_temp.write(urllib2.urlopen(url).read()) img_temp.flush() im.file.save(img_filename, File(img_temp)) 
from myapp.models import Photo import urllib from urlparse import urlparse from django.core.files import File img_url = 'http://www.site.com/image.jpg' photo = Photo() # set any other fields, but don't commit to DB (ie. don't save()) name = urlparse(img_url).path.split('/')[-1] content = urllib.urlretrieve(img_url) # See also: http://docs.djangoproject.com/en/dev/ref/files/file/ photo.image.save(name, File(open(content[0])), save=True)
from myapp.models import Photo import urllib from urlparse import urlparse from django.core.files import File img_url = 'http://www.site.com/image.jpg' photo = Photo() # set any other fields, but don't commit to DB (ie. don't save()) name = urlparse(img_url).path.split('/')[-1] content = urllib.urlretrieve(img_url) # See also: http://docs.djangoproject.com/en/dev/ref/files/file/ photo.image.save(name, File(open(content[0])), save=True) 

ImageField只是一个string,相对于您的MEDIA_ROOT设置的path。 只需保存文件(您可能想要使用PIL来检查它是一个图像),并使用其文件名填充字段。

所以它和你的代码有所不同,因为你需要将你的urllib.urlopen的输出保存到文件中(在你的介质位置中),找出path并保存到你的模型中。

我在Python 3上这样做,它应该对Python 2进行简单的改编。这是基于我所知道的,我检索的文件很小。 如果你的不是,我可能会build议写回应文件,而不是缓冲在内存中。

BytesIO是需要的,因为Django在文件对象上调用seek(),urlopen响应不支持seek。 您可以将read()返回的bytes对象传递给Django的ContentFile。

 from io import BytesIO from urllib.request import urlopen from django.core.files import File # url, filename, model_instance assumed to be provided response = urlopen(url) io = BytesIO(response.read()) model_instance.image_field.save(filename, File(io)) 

结合Chris Adams和Stan所说的和更新Python 3上的工作,如果你安装了Requests,你可以这样做:

 from urllib.parse import urlparse import requests from django.core.files.base import ContentFile from myapp.models import Photo img_url = 'http://www.example.com/image.jpg' name = urlparse(img_url).path.split('/')[-1] photo = Photo() # set any other fields, but don't commit to DB (ie. don't save()) response = requests.get(img_url) if response.status_code == 200: photo.image.save(name, ContentFile(response.content), save=True) 

Django的ContentFile文档和请求文件下载示例中的更多相关文档。

这是正确的和工作的方式

 class Product(models.Model): upload_path = 'media/product' image = models.ImageField(upload_to=upload_path, null=True, blank=True) image_url = models.URLField(null=True, blank=True) def save(self, *args, **kwargs): if self.image_url: import urllib, os from urlparse import urlparse filename = urlparse(self.image_url).path.split('/')[-1] urllib.urlretrieve(self.image_url, os.path.join(file_save_dir, filename)) self.image = os.path.join(upload_path, filename) self.image_url = '' super(Product, self).save() 

如果您在Django项目中使用file uploadfunction,则必须先安装Pillow:

 pip install pillow==2.6.1 

请记住在settings.py中设置媒体文件的url:

 MEDIA_ROOT = 'media/' 

然后,在您的models.py中,添加以下图像字段:

 userlogo = models.ImageField(upload_to="userlogo/", blank=True, null=True) 

编写这段代码之后,使用下面的代码迁移模型:

 python manage.py makemigrations python manage.py migrate 

现在您可以使用图像字段上传图像文件。 图像文件将被上传到YOUR_PROJECT_ROOT / media / userlogo目录。 您不需要手动创build“userlogo”文件夹。