假设我想在APIView.get中返回一个包含2个属性的(非模型)对象,其中一个是模型对象,另一个是二进制图像
我尝试了几种方法,并且遇到了序列化程序的问题。
谢谢!
串行:
class MyCustomSerializer(serializers.ModelSerializer):
class Meta:
model = MyCustom
fields = '__all__'
查看:
class MyCustomGet(APIView):
def get(self, request, format=None):
serializer = MyCustomSerializer
obj = s.get_custom()
return Response({"obj": serializer(obj.obj).data, "image": obj.image})
get_custom:
class CustomClass:
obj = None
image = None
def get_custom():
r = CustomClass()
r.obj = MyCustom.objects.all().first()
r.image = PIL.Image.open('file/path.png')
return r
答案 0 :(得分:3)
您正尝试在JSON响应(字符串)中呈现图像(二进制数据)。这不行。如果要在JSON字符串中传递图像,则必须将其编码为字符串,然后在客户端对其进行解码。一个常见的例子是base64编码的字符串:
import io
import base64
...
def get_custom():
...
image = PIL.Image.open('file/path.png')
stream = io.StringIO()
image.save(stream, format='PNG')
return base64.b64encode(stream.getvalue())
虽然对REST端点设计一无所知,但我认为更好的解决方案是使用单独的视图声明子资源。假设您的REST模式中有MyCustom
资源可由api/mycustom/:id/
访问并由MyCustomGet
视图提供,例如单独的视图可能负责在api/mycustom/:id/pic/
:
import django.http
class MyCustomPicView(APIView):
def get(self, request):
...
image = PIL.Image.open('file/path.png')
return django.http.HttpResponse(image, content_type='image/png')
答案 1 :(得分:1)
我不确定这是否有用,但这就是我为类似情况所做的。我有一个主模型对象,以及一个我想要标记的半相关对象。
基本上,如果您的CustomClass模型与您需要包含的图像有某种关联,只需直接在序列化程序实例中获取它。
这就是我尝试这样做的方式:
class MyCustomSerializer(serializers.ModelSerializer):
image_binary = serializers.SerializerMethodField()
class Meta:
model = MyCustom
fields = '__all__'
def get_image_binary(self, obj):
return WhateverModel.objects.get(relation=obj).attribute
这只是为模型序列化器添加了一些额外的数据,由序列化器即时计算。您甚至可以为image_binary设置第二个序列化程序,并且在get_image_binary()中只返回序列化程序的.data,就像在视图中一样。
这当然依赖于MyCustom对象以某种方式与图像二进制文件隐式相关的事实。
答案 2 :(得分:1)
首先,在序列化程序中,您提到的模型为java.security.interfaces.RSAPrivateKey
,而您的实际型号名称为MyCustom
。不知道这是否相关。如果图像是问题,您可以将图像转换为字符串,并将其转换回视图/您想要使用它的任何位置。
CustomClass
将其转换回图像:
class CustomClass:
obj = None
image = None
def get_custom():
r = CustomClass()
r.obj = MyCustom.objects.all().first()
import base64
with open("file/path.png", "rb") as imageFile:
str_ = base64.b64encode(imageFile.read())
r.image = str_
return r
我不知道您的具体用例是什么,但这种结构看起来并不正确。我会使用fh = open("imageToSave.png", "wb")
fh.write(r.image.decode('base64'))
fh.close()
来存储图像,而在序列化程序中,我只需返回ImageField
。