Search code examples
pythondjangodjango-formsdjango-file-uploadsorl-thumbnail

Django sorl: not enough values to unpack (expected 2, got 1)


I am trying to have a form to generate thumbnails from images that will be uploaded

I will be using sorl for the thumb generation and I am following the following documentation:

When I try to generate the thumbnail I get the error of

not enough values to unpack (expected 2, got 1)

I dont understand what I am doing wrong, in summary I upload the image and this get saved in my root directory, then im trying to create the thumb

Also is there a way to void saving this original image in the root? I am planning to send both Image and thumb to google cloud storage

My forms.py:

from django import forms
class FileFieldForm(forms.Form):
    file_field = forms.FileField(widget=forms.ClearableFileInput(attrs={'multiple': True}))

My html file: upload.html

<html>
    <head></head>
    <body>
        <h3>Read File Content</h3>
        <form enctype="multipart/form-data" action="" method="post">
            {% csrf_token %}
            {{ form }}
            <input type="submit" value="Save">
        </form>
    </body>
</html>

My views.py looks like:

from sorl.thumbnail import ImageField, get_thumbnail
from .forms import FileFieldForm

class FileFieldView(FormView):
    form_class = FileFieldForm
    template_name = 'app_workflow/upload.html'  # Replace with your template.
    success_url = '/photo'  # Replace with your URL or reverse().

    def post(self, request, *args, **kwargs):
        form_class = self.get_form_class()
        form = self.get_form(form_class)
        files = request.FILES.getlist('file_field')
        if form.is_valid():
            for f in files:
                with open(f.name, 'wb+') as destination:
                    for chunk in f.chunks():
                        destination.write(chunk)
                    im = get_thumbnail(f.name, '100x100', crop='center', quality=99)

            return self.form_valid(form)
        else:
            return self.form_invalid(form)

Solution

  • As you have said in the question, you do not want to store in root and generate thumbnail. Then I would suggest something like this:

    from PIL import Image
    
    class FileFieldView(FormView):
        form_class = FileFieldForm
        template_name = 'app_workflow/upload.html'  # Replace with your template.
        success_url = '/photo'  # Replace with your URL or reverse().
    
        def form_valid(self, *args, **kwargs):
            img_size = (100, 100)
            files = self.request.FILES.getlist('file_field')
            for f in files:
               im = Image.open(f)
               im.thumbnail(img_size) 
               # your thumbnail image is in memory now
               # you can now store it in your model and use django-storages to upload it to gcloud
    
            return super().form_valid(*args, **kwargs)
    

    Here I am not storing images and directly loading it in the PIL.Image module to generate thumbnails. You can use django-storages to upload data from FileField to gcloud.

    Storing in root:

    Then you can change the code like this:

    for f in files:
       for chunk in f.chunks():
          destination.write(chunk)
       im = Image.open(f)
       im.thumbnail(img_size)
       im.save('thumb_{}'.format(f.name))