下载远程图像并将其保存到Django模型

问题描述 投票:23回答:6

我正在编写一个Django应用程序,它将获取特定URL的所有图像并将它们保存在数据库中。

但我没有介绍如何在Django中使用ImageField。

settings.朋友

MEDIA_ROOT = os.path.join(PWD, "../downloads/")

# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash.
# Examples: "http://example.com/media/", "htp://media.example.com/"
MEDIA_URL = '/downloads/'

models.朋友

class images_data(models.Model):
        image_id =models.IntegerField()
        source_id = models.IntegerField()
        image=models.ImageField(upload_to='images',null=True, blank=True)
        text_ind=models.NullBooleanField()
        prob=models.FloatField()

download_IMG.朋友

def spider(site):
        PWD = os.path.dirname(os.path.realpath(__file__ ))
        #site="http://en.wikipedia.org/wiki/Pune"
        hdr= {'User-Agent': 'Mozilla/5.0'}
        outfolder=os.path.join(PWD, "../downloads")
        #outfolder="/home/mayank/Desktop/dreamport/downloads"
        print "MAYANK:"+outfolder
        req = urllib2.Request(site,headers=hdr)
        page = urllib2.urlopen(req)
        soup =bs(page)
        tag_image=soup.findAll("img")
        count=1;
        for image in tag_image:
                print "Image: %(src)s" % image
                filename = image["src"].split("/")[-1]
                outpath = os.path.join(outfolder, filename)
                urlretrieve('http:'+image["src"], outpath)
                im = img(image_id=count,source_id=1,image=outpath,text_ind=None,prob=0)
                im.save()
                count=count+1

我在一个视图中调用download_imgs.py

        if form.is_valid():
                url = form.cleaned_data['url']
                spider(url)
python django django-models
6个回答
37
投票

Django Documentation始终是一个好的起点

class ModelWithImage(models.Model):
    image = models.ImageField(
        upload_to='images',
    )

更新

所以这个脚本有效。

  • 循环图像下载
  • 下载图片
  • 保存到临时文件
  • 适用于模特
  • 保存模型

.

import requests
import tempfile

from django.core import files

# List of images to download
image_urls = [
    'http://i.thegrindstone.com/wp-content/uploads/2013/01/how-to-get-awesome-back.jpg',
]

for image_url in image_urls:
    # Steam the image from the url
    request = requests.get(image_url, stream=True)

    # Was the request OK?
    if request.status_code != requests.codes.ok:
        # Nope, error handling, skip file etc etc etc
        continue

    # Get the filename from the url, used for saving later
    file_name = image_url.split('/')[-1]

    # Create a temporary file
    lf = tempfile.NamedTemporaryFile()

    # Read the streamed image in sections
    for block in request.iter_content(1024 * 8):

        # If no more file then stop
        if not block:
            break

        # Write image block to temporary file
        lf.write(block)

    # Create the model you want to save the image to
    image = Image()

    # Save the temporary image to the model#
    # This saves the model so be sure that is it valid
    image.image.save(file_name, files.File(lf))

一些参考链接:

  1. requests - “HTTP for Humans”,我更喜欢urllib2
  2. qazxsw poi - 保存临时文件而不是磁盘
  3. Django filefield tempfile

17
投票

如果你想保存下载的图像而不先将它们保存到磁盘(不使用save等),那么有一种简单的方法可以做到这一点。

这比下载文件并将其写入磁盘稍快一些,因为它全部在内存中完成。请注意,此示例是为Python 3编写的 - 该过程在Python 2中类似,但略有不同。

NamedTemporaryFile

其中from django.core import files from io import BytesIO import requests url = "https://example.com/image.jpg" resp = requests.get(url) if resp.status_code != requests.codes.ok: # Error handling here fp = BytesIO() fp.write(resp.content) file_name = url.split("/")[-1] # There's probably a better way of doing this but this is just a quick example your_model.image_field.save(file_name, files.File(fp)) 是您要保存的模型的实例,your_model.image_field的名称。

有关更多信息,请参阅ImageField的文档。


1
投票

作为我认为你问的一个例子:

在forms.py中:

io

在models.py中:

imgfile = forms.ImageField(label = 'Choose your image', help_text = 'The image should be cool.')

因此,将有来自用户的POST请求(当用户完成表单时)。该请求基本上包含数据字典。字典保存提交的文件。要将请求集中在字段中的文件(在我们的示例中为ImageField),您将使用:

imgfile =   models.ImageField(upload_to='images/%m/%d')

您可以在构造模型对象时使用它(实例化模型类):

request.FILES['imgfield']

要以简单的方式保存,您只需使用赋予对象的save()方法(因为Django非常棒):

newPic = ImageModel(imgfile = request.FILES['imgfile'])

默认情况下,您的图像将存储在settings.py中为MEDIA_ROOT指定的目录中。

访问模板中的图像:

if form.is_valid():
    newPic = Pic(imgfile = request.FILES['imgfile'])
    newPic.save()

网址可能很棘手,但这里是一个简单网址模式的基本示例来调用存储的图像:

<img src="{{ MEDIA_URL }}{{ image.imgfile.name }}"></img>

我希望它有所帮助。


0
投票

尝试这样做而不是分配路径到图像...

urlpatterns += patterns('',
        url(r'^media/(?P<path>.*)$', 'django.views.static.serve', {
            'document_root': settings.MEDIA_ROOT,
        }),
   )

像这样使用上面的功能..

    import urllib2
    from django.core.files.temp import NamedTemporaryFile
    def handle_upload_url_file(url):
        img_temp = NamedTemporaryFile()
        opener = urllib2.build_opener()
        opener.addheaders = [('User-agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:15.0) Gecko/20120427 Firefox/15.0a1')]
        img_temp.write(opener.open(url).read())
        img_temp.flush()
        return img_temp

0
投票

类似于@ boltfrombluesky上面的回答,你可以在Python 3中做到这一点,没有任何外部依赖,如下所示:

    new_image = images_data()
    #rest of the data in new_image and then do this.
    new_image.image.save(slug_filename,File(handle_upload_url_file(url)))
    #here slug_filename is just filename that you want to save the file with.

-2
投票
from os.path import basename
import urllib.request
from urllib.parse import urlparse
import tempfile

from django.core.files.base import File

def handle_upload_url_file(url, obj):
    img_temp = tempfile.NamedTemporaryFile(delete=True)
    req = urllib.request.Request(
        url, data=None,
        headers={
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36'
        }
    )
    with urllib.request.urlopen(req) as response:
        img_temp.write(response.read())
    img_temp.flush()
    filename = basename(urlparse(url).path)
    result = obj.image.save(filename, File(img_temp))
    img_temp.close()
    return result
© www.soinside.com 2019 - 2024. All rights reserved.