Django. How to save a ContentFile edited with Pillow

≡放荡痞女 提交于 2019-12-12 21:18:52

问题


I'm trying to save an image I download with requests and then edit with Pillow to ImageField in a model. But the object is being created without the image.

This is what I have:

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 ...')

It creates the object but with no image. Please help. I've been trying to solve this for hours.


回答1:


Background

Though InMemoryUploadedFile is primarily intended to be used by MemoryFileUploadHandler, it can be used for other purposes as well. It should be noted that MemoryFileUploadHandler is for handling the situation when a user uploads a file to your server using a webform or a widget. However what you are handling is a situation the user merely provides a link and you download a file on to your web server.

Let us also recall that ImageFile is essentially a reference to a file stored on your filesystem. Only the name of the file is entered in the database and the file's content itself is stored in the storage system. Django allows you to specify different storage systems so that the file can be saved on the cloud if you need to.

Solution

All you need to do is to pass the content of the image that you generate using Pillow with a filename to ImageField. And that content can be sent through a InMemoryUploaded file or a ContentFile. However there isn't a need to use both.

So this is your model.

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

    # over ride of save method not needed here.

This is your view.

  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')

Footnotes

Exception handling has been added because things can and will go wrong.

Instead of using JPEG and image/jpeg you should use answers.headers['Content-type'] and choose the appropriate one.




回答2:


Try this self.image.save(some_file_path, ContentFile(image_stringio)). And it seems to me that you don't need to override save() in model.



来源:https://stackoverflow.com/questions/37153809/django-how-to-save-a-contentfile-edited-with-pillow

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!