Django Rest Framework:将图像分配给上传文件夹中的模型字段

Django Rest Framework: Assign image to model field from uploaded folder

我正在通过 Django - Rest - Framework HTTP 将 .zip 文件发布到我的 Django 应用程序。这个 zip 文件是一个包含多个文件的文件夹,其中有一个图像。我想在上传后提取文件夹,select 图像并将其分配给模型。这可能吗?如果没有,也许我可以写一个 属性 来获取缩略图?我希望稍后能够显示图库中的所有缩略图。

类似于:

class FUploadSerializer(serializers.ModelSerializer):
    file = serializers.FileField()

    class Meta:
        model = FUpload
        fields = ('created','file')


class FUpload(models.Model):
    created = models.DateTimeField(auto_now_add=True)
    file = models.FileField(upload_to=get_path)
    thumbnail = ImageField() ??? # get from uploaded folder

编辑

我尝试了以下方法,但得到的是:"image":[ "The submitted data was not a file. Check the encoding type on the form." ] 。我是在完全倒退地思考这个问题吗?是否"better" 让客户端处理分别发送图像和.zip 文件夹(数据从脚本发送)? ModelViewSet 是处理这个问题的正确位置吗?

class Thumbnail(models.Model):
    image = models.ImageField()
    file = models.FileField()


class ThumbnailViewSet(viewsets.ModelViewSet):
    queryset = Thumbnail.objects.all()
    serializer_class = ThumbnailSerializer
    parser_classes = (MultiPartParser, FormParser,)

    def perform_create(self, serializer):
        file = self.request.FILES['file']      
        zf = zipfile.ZipFile(file)
        content_list = zf.namelist()
        imgdata = zf.open(content_list[0])
        serializer.save(image=imgdata)

class ThumbnailSerializer(serializers.ModelSerializer):
    file = serializers.FileField()
    image = serializers.ImageField(allow_empty_file=True, required=False)

    class Meta:
        model = Thumbnail
        fields = ('file', 'image')

为了完成这项工作,您将需要实现自己的自定义解析器,该解析器可以处理传入的 zip 文件、将其解压缩并将某些文件分配给特定字段。

class ZipParser(FileUploadParser):
    """
    Parses an incoming ZIP file into separate fields.

    The ZIP file is expected to be the only data passed in the request,
    use the `MultiPartParser` as a base if it will be passed in using form
    data instead.
    """

    media_type = 'application/zip'  # only needed for `FileUploadParser`

    def parse(self, stream, media_type=None, parser_context=None):
        import io
        import zipfile

        parsed = super(ZipParser, self).parse(
            self,
            media_type=media_type,
            parser_context=parser_context
        )

        data = parsed.files

        data['zip_file'] = data['file']  # Keep the original zip file as `zip_file`
        parsed_file = data['file']  # Also store a reference to the original file so it can be used

        # Try to parse the zip file
        # This should also handle proper file handling (such as not passing a zip file)
        with zipfile.ZipFile(parsed_file) as zip_file:
            # Get the `bytes` object for a file using `read(file_name)`
            image_data = zip_file.read('image.png')  # Replace `image.png` with the image file
            file_data = zip_file.read('info.txt')

            # DRF expects that files are using an IO compatible object, so we need `BytesIO` here
            image_stream = io.BytesIO(image_data)
            file_stream = io.BytesIO(file_data)

            # The changed files should go back onto the files dictionary
            data['image'] = image_stream
            data['file'] = file_stream

        return parsed

如果您使用自己的自定义视图,您也可以在将数据传递到序列化程序之前在解析器外部执行此操作。