【问题标题】:Django. How to save a ContentFile edited with Pillow姜戈。如何保存使用 Pillow 编辑的 ContentFile
【发布时间】:2016-05-11 05:32:41
【问题描述】:

我正在尝试保存使用requests 下载的图像,然后在模型中使用Pillow 编辑到ImageField。但是对象是在没有图像的情况下创建的。

这就是我所拥有的:

settings.py

MEDIA_ROOT = BASE_DIR + "/media/"
MEDIA_URL = MEDIA_ROOT + "/magicpy_imgs/"

models.py

def create_path(instance, filename):
    path = "/".join([instance.group, instance.name])
    return path

class CMagicPy(models.Model):
    image = models.ImageField(upload_to=create_path)
    ....

    # Custom save method
    def save(self, *args, **kwargs):
        if self.image:
            image_in_memory = InMemoryUploadedFile(self.image, "%s" % (self.image.name), "image/jpeg", self.image.len, None)
            self.image = image_in_memory

        return super(CMagicPy, self).save(*args, **kwargs)

forms.py

class FormNewCard(forms.Form):
    imagen = forms.URLField(widget=forms.URLInput(attrs={'class': 'form-control'}))

views.py

def new_card(request):
    template = "hisoka/nueva_carta.html"

    if request.method == "POST":

        form = FormNewCard(request.POST)

        if form.is_valid():

            url_image = form.cleaned_data['imagen']
            group = form.cleaned_data['grupo']
            name = form.cleaned_data['nombre']
            description = form.cleaned_data['descripcion']

            answer = requests.get(url_image)
            image = Image.open(StringIO(answer.content))
            new_image = image.crop((22, 44, 221, 165))
            stringio_obj = StringIO()

            try:
                new_image.save(stringio_obj, format="JPEG")
                image_stringio = stringio_obj.getvalue()
                image_file = ContentFile(image_stringio)
                new_card = CMagicPy(group=group, description=description, name=name, image=image_file)
                new_card.save()

            finally:
                stringio_obj.close()

            return HttpResponse('lets see ...')

它创建对象但没有图像。请帮忙。我已经尝试解决这个问题好几个小时了。

【问题讨论】:

标签: python django pillow


【解决方案1】:

背景

虽然InMemoryUploadedFile 主要供MemoryFileUploadHandler 使用,但它也可以用于其他目的。需要注意的是,MemoryFileUploadHandler 用于处理用户使用网络表单或小部件上传文件到您的服务器的情况。但是,您正在处理的情况是用户仅提供了一个链接,而您下载一个文件到您的网络服务器上。

让我们还记得ImageFile 本质上是对存储在文件系统上的文件的引用。在数据库中只输入文件的名称,文件的内容本身存储在存储系统中。 Django 允许您指定不同的存储系统,以便在需要时可以将文件保存在云上。

解决方案

您需要做的就是将使用Pillow 生成的图像内容和文件名传递给ImageField。该内容可以通过InMemoryUploaded 文件ContentFile 发送。但是没有必要同时使用两者。

这就是你的模型。

class CMagicPy(models.Model):
    image = models.ImageField(upload_to=create_path)

    # over ride of save method not needed here.

这是你的观点。

  try:
     # form stuff here

     answer = requests.get(url_image)

     image = Image.open(StringIO(answer.content))
     new_image = image.rotate(90) #image.crop((0, 0, 22, 22))
     stringio_obj = StringIO()


     new_image.save(stringio_obj, format="JPEG")
     image_file = InMemoryUploadedFile(stringio_obj, 
         None, 'somefile.jpg', 'image/jpeg',
         stringio_obj.len, None)

     new_card = CMagicPy()
     new_card.image.save('bada.jpg',image_file)
     new_card.save()

 except:
     # note that in your original code you were not catching
     # an exception. This is probably what made it harder for
     # you to figure out what the root cause of the problem was
     import traceback
     traceback.print_exc()
     return HttpResponse('error')
 else:
     return HttpResponse('done')

脚注

添加了异常处理,因为事情可能而且将会出错。

您应该使用 answers.headers['Content-type'] 并选择合适的,而不是使用 JPEG 和 image/jpeg。

【讨论】:

    【解决方案2】:

    试试这个self.image.save(some_file_path, ContentFile(image_stringio))。在我看来,您不需要在模型中覆盖 save()

    【讨论】:

    • 感谢您的回答,这让我意识到不可能将save 调用到URLField +1 ...尝试将其更改为ImageField,但它没有'没有意义(并且不起作用),因为用户提交了一个 URL,我将使用该 URL 从另一个网站请求图像。所以...我决定ModelForm 和CBV 在这种情况下对我没有帮助,并将所有内容更改为基于函数的视图。它仍然没有保存图像,但至少这段代码对我来说更有意义。有任何想法吗?尝试在模型中使用和不使用自定义保存方法。
    猜你喜欢
    • 2016-08-18
    • 2011-04-12
    • 2011-05-15
    • 2018-04-12
    • 2020-08-17
    • 2020-10-07
    • 1970-01-01
    • 2020-08-22
    相关资源
    最近更新 更多