【问题标题】:How to upload an image from URL如何从 URL 上传图片
【发布时间】:2017-04-09 21:45:21
【问题描述】:

我有两种上传图片的方法。 1是从用户的文件中选择图像,另一种是通过URL上传图像。

模型

class Post(models.Model):
    ...
    image = models.FileField(null=True, blank=True)
    imageURL = models.URLField(null=True, blank=True)

    def download_file_from_url(self):
        print('DOWNLOAD') #prints "DOWNLOAD"
        # Stream the image from the url
        try:
            request = requests.get(self, stream=True)
        except requests.exceptions.RequestException as e:
            # TODO: log error here
            return None

        if request.status_code != requests.codes.ok:
            # TODO: log error here
            return None

        # 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)
            return files.File(lf)

html

    <input id="id_image" type="file" name="image" /> <!--upload from file-->
    {{ form_post.imageURL|placeholder:"URL" }} <!--url upload-->

从文件上传图像工作正常,用户只需点击输入并选择他们的文件。但是,当用户决定改用 URL 选项时。如何获取该 URL 字符串并将其设为 image 字段的值?

观看次数

    ...
    if form_post.is_valid():
        instance = form_post.save(commit=False)
            if instance.imageURL:
                instance.image = Post.download_file_from_url(instance.imageURL)
                instance.save()

urls.py

...
if settings.DEBUG:
    urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

settings.py

...
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

【问题讨论】:

    标签: python django


    【解决方案1】:

    Python 3 兼容方法:

    import requests
    import tempfile
    from django.core import files
    
    def download_file_from_url(url):
        # Stream the image from the url
        try:
            request = requests.get(url, stream=True)
        except requests.exceptions.RequestException as e:
            # TODO: log error here
            return None
    
        if request.status_code != requests.codes.ok:
            # TODO: log error here
            return None
    
        # 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)
    
        return files.File(lf)
    #Do this in your view
    if self.url and not self.photo:
           self.photo = download_file_from_url(url)
    

    【讨论】:

    • 对不起,我有点困惑。我是否将download_file_from_url() 放在我的模型中,然后放在我的视图中?
    • @Zorgan 最后一点应该在您的观点中。该功能是您的电话。无论你把它放在哪里,你都会导入它。如果你让 download_file_from_url 成为一个类方法,那就更方便了。
    • 好的,我已经把所有的代码都放进去了,它成功地调用了这个函数,没有错误。但是它不会将任何图像保存到数据库中。如果你想看看,我已经更新了我的编辑。
    • 使用 ImageField 代替 FileField 并指定 upload_location。这对我有用。在您的模型中,您还没有指定上传位置。所以它不会将其上传到您的媒体。
    • 我在我的urls.py 中指定了上传位置,并在我的编辑中添加。为什么我必须使用 ImageField 而不是 FileField?
    【解决方案2】:

    您不能在 FileField 上放置字符串。它必须是一个文件。不过有一个解决方法。您需要从服务器上的 URL 下载文件,然后将其保存到数据库中。

    以下代码可能对您有所帮助:

    class CachedImage(models.Model):
        url = models.CharField(max_length=255, unique=True)
        photo = models.ImageField(upload_to=photo_path, blank=True)
    
        def cache(self):
            """Store image locally if we have a URL"""
    
            if self.url and not self.photo:
                result = urllib.request.urlretrieve(self.url)
                self.photo.save(
                        os.path.basename(self.url),
                        File(open(result[0]))
                        )
                self.save()
    

    【讨论】:

    • 知道我该怎么做吗?我正在查看urllib,它显然适用于 python2,但我正在使用 python3。
    • 我看过了,但仍然有点困惑如何使用urlretrieve..我已经在 url 字符串上使用了它,但从那里我不知道如何将图像保存在数据库。你能看看我的编辑吗?
    • 我编辑了我的答案。检查并告诉我它是否适合您。介意从 django.core.files 导入适当的库 import File import urllib
    • 刚刚尝试了您的代码,但我无法添加unique=True,因为它给出了UNIQUE constraint failed 错误。所以我只是用max_length=255, blank=True, null=True 代替url。但是它甚至没有调用cache() 函数,我在cache() 中添加了一个打印语句并且它不打印。此外,我在发布后查看了我的媒体文件夹,图像没有保存在数据库中(media 文件夹)。有什么想法吗?
    猜你喜欢
    • 1970-01-01
    • 2017-07-16
    • 2011-08-05
    • 1970-01-01
    • 2021-07-19
    • 1970-01-01
    • 2019-03-11
    • 2019-02-16
    • 1970-01-01
    相关资源
    最近更新 更多