Django: Webp conversion fails and creates empty picture element while all debugging efforts fail

Question:

Update:

After making some smaller changes to the accepted answer i was able to resolve it:

class GalleryView(APIView):
  parser_class = (FileUploadParser,)

  def post(self, request):
    # Extract the facility ID and list of pictures from the request
    print('post method called')
    facility_id = request.data.get('facility')
    pictures = request.data.getlist('pictures')

    print(facility_id, pictures)

    facility = get_object_or_404(Facility, id=facility_id)

    try:
      gallery = Gallery.objects.get(facility=facility)
    except Gallery.DoesNotExist:
      gallery = Gallery.objects.create(facility=facility)

    with transaction.atomic():
        for picture in pictures:
            print('for loop executing')
            try:
                webp_image = BytesIO()
                image = Image.open(picture)
                image.save(webp_image, format='webp', quality=5)
                print(webp_image)
                
                file_name = picture.name
                if picture.name.lower().endswith(('.jpg', '.jpeg', '.png')):
                    file_name = f"{os.path.splitext(picture.name)[0]}.webp"
                else:
                    file_name = picture.name
                file_object = ContentFile(webp_image.getvalue(), name=file_name)
                print(file_object)
                picture_obj = Picture.objects.create(picture=file_object)
                print(picture_obj)
                gallery.pictures.add(picture_obj)
                print(gallery)
            except Exception as e:
                print(type(e))
                continue

    serializer = GallerySerializer(gallery)
    return Response(serializer.data, status=201)
            

I’m trying to create an upload form to upload multiple images that need to be converted to webp. Everything worked fine until i added the webp conversion bits.
I tried adding exceptions and print statements to track down the issue but no exceptions were raised.
Instead it shows all signs of success and creates an empty "picture" element in the database. I`m using the django cookiecutter project with pillow.
Does anyone know what might be causing this?

models.py

def upload_gallery_image(instance, filename):
  # Print a message to indicate that the function was called
  print(instance, filename)
  return f'galleries/{instance.facility.id}/{filename}'


class Picture(models.Model):
  picture = models.ImageField(upload_to=upload_gallery_image)
  
class Gallery(models.Model):
  facility = models.ForeignKey(Facility, on_delete=models.CASCADE, related_name='tourphotos')
  pictures = models.ManyToManyField(Picture, related_name='galleries')

views.py

class GalleryView(APIView):
  parser_class = (FileUploadParser,)

  def post(self, request):
    # Extract the facility ID and list of pictures from the request
    print('post method called')
    facility_id = request.data.get('facility')
    pictures = request.data.getlist('pictures')

    print(facility_id, pictures)

    facility = get_object_or_404(Facility, id=facility_id)

    try:
      gallery = Gallery.objects.get(facility=facility)
    except Gallery.DoesNotExist:
      gallery = Gallery.objects.create(facility=facility)

    for picture in pictures:
        print('for loop executing')
        try:
            webp_image = BytesIO()
            image = Image.open(picture)
            image.save(webp_image, format='webp', quality=75)
            print(webp_image)
            file_object = ContentFile(webp_image.getvalue())
            print(file_object)
            picture_obj = Picture.objects.create(picture=file_object)
            print(picture_obj)
            gallery.pictures.add(picture_obj)
            print(gallery)
        except Exception as e:
            print(type(e))
            continue

    webp_image.close()

    serializer = GallerySerializer(gallery)
    return Response(serializer.data, status=201)


serializers.py

class PictureSerializer(serializers.ModelSerializer):
    class Meta:
        model = Picture
        fields = ('id', 'picture')

class GallerySerializer(serializers.ModelSerializer):
    pictures = PictureSerializer(many=True)
    class Meta:
        model = Gallery
        fields = ('id', 'pictures')

Server response:

django          | post method called
django          | 24 [<InMemoryUploadedFile: 156f9f885e468c60dd7d6d539f2ee1bb.webp (image/webp)>]
django          | for loop executing
django          | <_io.BytesIO object at 0x7fbfdb14eef0>
django          | Raw content
django          | Picture object (304)
django          | Gallery object (59)
django          | 172.21.0.1 - - [02/Jan/2023 11:09:44] "POST /api/multipleupload/ HTTP/1.1" 201 -
Asked By: Matthias

||

Answers:

Try adding name to the ContentFile, in your case change to this:

file_object = ContentFile(webp_image.getvalue(), name=picture)

ContentFile will not create file without filename.

Answered By: Nikolay Pavlin