Python django rest框架文件上载和嵌套的可写序列化程序

Python django rest框架文件上载和嵌套的可写序列化程序,python,django,django-rest-framework,Python,Django,Django Rest Framework,注释具有图像外键属性,因此图像可能具有多个注释。我想通过对图像端点的post请求(包括该图像的注释列表)创建一个带有嵌套注释的图像。将json编码的数据发布到images端点确实有效,并创建具有适当注释的图像 但是,当我尝试上载实际图像时,我必须使用多部分/表单编码的post请求而不是json请求来实现文件上载。现在我很难得到这个请求中包含的图像注释嵌套列表。也许我可以把一个json编码的字符串放在某个表单字段中,然后在视图中手动解析它,覆盖request.DATA,但这看起来真的很难看 我想知

注释具有图像外键属性,因此图像可能具有多个注释。我想通过对图像端点的post请求(包括该图像的注释列表)创建一个带有嵌套注释的图像。将json编码的数据发布到images端点确实有效,并创建具有适当注释的图像

但是,当我尝试上载实际图像时,我必须使用多部分/表单编码的post请求而不是json请求来实现文件上载。现在我很难得到这个请求中包含的图像注释嵌套列表。也许我可以把一个json编码的字符串放在某个表单字段中,然后在视图中手动解析它,覆盖request.DATA,但这看起来真的很难看


我想知道是否有更好的方法来实现我的目标:)。

如果很难获取请求中包含的图像注释嵌套列表,这是什么意思?当您发送
multpart/form data
post请求时,嵌套的符号列表数据是否包含在request.data中?(请使用
request.data
而不是
request.data
request.FILES
)。请使用一些调试工具,如
pdb
检查您的
请求。数据

为了支持可写的嵌套序列化程序,我认为您应该对
POST
方法的
create()。很抱歉没有直接给出答案,我需要更多关于你们型号的细节


如果您想发布
JSON
而不是
multipart/form data
,您可以使用
base64
来表示图形(但文件大小将增大近33%)

您可以使用formencode.variabledecode.variable_decode()

例如:

class AnnotationSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Annotation


class ImageSerializer(serializers.HyperlinkedModelSerializer):
    annotations = AnnotationSerializer(many=True, required=False)

    class Meta:
        depth = 1
        model = Image
        exclude = ('owner‘,)

我发现解决这个问题最简单的方法是编写一个自定义解析器来解析传入的多部分请求。我一直在使用它来进行实际的解析,但是您可以使用任何嵌套的formdata库。这需要很少的代码:

class ImageSerializer(serializers.HyperlinkedModelSerializer):

    ...

    def to_internal_value(self, value):
        return super(ImageSerializer, self).to_internal_value(variable_decode(value))
然后在
视图集中

from rest_framework import parsers
from formencode.variabledecode import variable_decode

class MultipartFormencodeParser(parsers.MultiPartParser):

    def parse(self, stream, media_type=None, parser_context=None):
        result = super().parse(
            stream,
            media_type=media_type,
            parser_context=parser_context
        )
        data = variable_decode(result.data)
        return parsers.DataAndFiles(data, result.files)

Formencode将列表表示为编码表单数据中的
-
项,将嵌套属性表示为
。因此,在您的示例中,客户端需要在请求中将注释编码为类似于
“annotation-1.name”
。显然,您仍然需要手动处理rest框架文档中提到的序列化程序中嵌套数据的更新

找到解决方案了吗?没有,我最终使用了一个特殊的图像端点。我面临同样的问题。特殊端点是什么意思?如果您也有嵌套文件,那么您可以通过执行
files=variable\u decode(result.files)
并将其传递到
return parsers.DataAndFiles(data,files)
class ImageViewSet(viewsets.ModelViewSet):
    ...
    parsers = (MultipartFormencodeParser,)
    ...