1

我有一个图像 url,我想在对象保存期间从中设置一个 ProcessedImageField 属性。到目前为止,我得到了这个:

 class Video(Media):
      url = models.URLField('url', max_length=256, default='')
      embed_url = models.URLField('embed url', max_length=256, default='')
      thumbnail = ProcessedImageField(upload_to='uploads',
                                  processors=[ResizeToFit(width=1024, height=1024, upscale=False)],
                                  format='JPEG',
                                  options={'quality': 75})


    def save(self, *args, **kwargs):
        from django.core.files.temp import NamedTemporaryFile
        import shutil
        import requests
        import re

        params = {
            'url': self.url,
            'autoplay': 1,
            'format': 'json',
        }

        try:
            data = requests.get('http://www.youtube.com/oembed', params=params).json()          
            embed_url = re.search('src=[\'"]([^\'"]*)[\'"]', data['html']).group(1)                
            thumbnail_url = data['thumbnail_url']
        except:
            pass

        response = requests.get(thumbnail_url, stream=True)
        img_temp = NamedTemporaryFile(delete=True)
        shutil.copyfileobj(response.raw, img_temp)

        # now image data are in img_temp, how to pass that to ProcessedImageField?

        super(Video, self).save(*args, **kwargs)
4

3 回答 3

1

此时您应该能够直接保存到该属性。

self.thumbnail.save("filename.ext", img_temp)
于 2013-10-15T20:19:37.670 回答
0

这是我的结果代码(没有错误处理)。最后,我以一种更简单的方式进行了操作,避免使用临时文件并改用 ContentFile。

class Video(Media):
    url = models.URLField('url', max_length=256, default='')
    embed_url = models.URLField('embed url', max_length=256, default='')
    author = models.CharField('author', max_length=64, default='', blank=True)
    thumbnail = ProcessedImageField(upload_to='uploads',
                                processors=[ResizeToFit(width=1024, height=1024, upscale=False)],
                                format='JPEG',
                                options={'quality': 75})

    def save(self, *args, **kwargs):
        from django.core.files.base import ContentFile
        import requests
        import re

        params = {
            'url': self.url,
            'format': 'json',
        }

        data = requests.get('http://www.youtube.com/oembed', params=params).json()
        embed_url = re.search('src=[\'"]([^\'"]*)[\'"]', data['html']).group(1)
        thumbnail_url = data['thumbnail_url']
        author = data['author_name']
        title = data['title']

        image_data = requests.get(thumbnail_url, stream=True).raw.data
        self.thumbnail.save(title, ContentFile(image_data), save=False)
        self.embed_url = embed_url
        self.author = author
        self.title = title

        super(Video, self).save(*args, **kwargs)
于 2013-10-15T22:03:31.577 回答
0

好的,我已经用 Python 3 的这段代码结束了 :) 它有内置的重试,它们之间有超时,并且支持下载大文件

def save_image_from_url(self, image_url):
    s = requests.Session()
    retries = Retry(total=5,
                    backoff_factor=0.1,
                    status_forcelist=[500, 502, 503, 504])
    s.mount('https://', HTTPAdapter(max_retries=retries))
    response = s.get(image_url, stream=True, timeout=9)
    # here just use whatever name you want, I've just retrieve the path from my custom field
    folder_name = Artist.image.field.upload_to.sub_path
    random_name = uuid.uuid4().hex + ".png"
    # creating folder if it doen't exist
    try:
        os.makedirs(os.path.join(settings.MEDIA_ROOT, folder_name))
    except OSError as e:
        if e.errno != errno.EEXIST:
            raise
    # loading image to tmp location and saving it, it's for large files because we can't handle them in memory
    tmp = tempfile.NamedTemporaryFile(delete=True)
    try:
        tmp.write(response.raw.read())
        with open(tmp.name, 'rb') as f:
            self.image.save(random_name, f)
    finally:
        tmp.close()

self.image在哪里ProcessedImageField

于 2017-09-18T09:06:41.710 回答