Django中WebP转换失败生成空Picture元素,调试无果求助
多图片上传转WebP后生成空Picture元素问题分析
我正在开发一个多图片上传表单,需要将上传图片转换为WebP格式。原本功能正常,但添加WebP转换逻辑后出现问题:无任何异常抛出,服务器日志显示执行成功,却在数据库中生成空的Picture元素。使用的技术栈为Django Cookiecutter项目及Pillow库。
更新:已解决的代码
对解决方案做少量修改后,问题成功解决:
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)
问题出现时的相关代码
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')
服务器响应日志
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 -
问题原因
缺少文件名参数:原代码中创建
ContentFile时仅传入了文件内容,未指定文件名:file_object = ContentFile(webp_image.getvalue())Django的
ImageField依赖文件名来确定存储路径(对应upload_to函数的filename参数)和文件格式标识,缺少文件名会导致Django无法正确处理文件存储逻辑,最终数据库中仅生成空的Picture记录,无实际文件关联。事务缺失(次要):原代码未使用事务包裹批量创建逻辑,若中途出现异常可能导致部分数据残留,但结合日志来看,本次问题的核心还是文件名缺失。
内容的提问来源于stack exchange,提问作者Matthias
相关产品推荐
相关产品推荐

