2017-11-15 19 views
2

2つのプロパティを関連付ける(非モデル)オブジェクトであるAPIView.getを返す場合、そのうちの1つはモデルオブジェクトであり、もう1つはバイナリ画像Django-Rest-Framework APIViewがモデルオブジェクトと画像を返す場合

私はいくつかの方法を試して、シリアライザに問題がありました。

ありがとうございました!

シリアライザ:

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 
+1

エラーが表示されることはありませんでしたか? –

答えて

2

イメージ(バイナリデータ)をJSONレスポンス(文字列)でレンダリングしようとしています。これはうまくいかないでしょう。 JSON文字列でイメージを渡す場合は、文字列としてエンコードしてクライアント側でデコードする必要があります。あなたのRESTエンドポイントのデザインについて何も知らないが、私の意見でより良い解決策は、別のビューでサブリソースを宣言するだろう

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()) 

:一般的な例としては、base64でエンコードされた文字列になります。 RESTスキーマのMyCustomリソースがapi/mycustom/:id/でアクセス可能であり、MyCustomGetビューのサービスを提供しているとします。別のビューには、api/mycustom/:id/pic/の下で対応するファイルを提供するための責任を負うことができます:MyCustomとして

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

私はbase64で考えていましたが、PIL Image Objectを送信することは確実ではありませんでした。クライアント側で多くの制限が課せられています。回答を投稿する前に、api-call /:id/image解決策、それは魅力のように働いています:) – Qsebas

+0

@ Qsebasうれしい私はあなたが正しい道にいることを確認することができました! – hoefling

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用の2番目のシリアライザを持つこともできますし、get_image_binary()でシリアライザの.dataを返すこともできます。

もちろん、MyCustomオブジェクトは暗黙的にイメージバイナリに関連しているという事実に依存します。

1

まず、シリアライザにあなたが言及したモデルと実際のモデル名は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を使用し、シリアライザでは単にimage.urlを返します。

関連する問題