Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
801 views
in Technique[技术] by (71.8m points)

python - Return image using Django REST framework Render

I uploaded images using Django REST Framework. Now I'm trying to return the same image as response.

views.py

class ImageUploadView(viewsets.ModelViewSet):
    queryset = ImageModel.objects.all()
    serializer_class = ImageSerializer

    def create(self, request, *args, **kwargs):
        userID = (request.data.get('userID'))
        serializer = self.get_serializer(data=request.data)
        if not UserModel.objects.filter(id=userID).exists():
            return Response(data={"detail": "Invalid UserID"})
        else:
            if serializer.is_valid():
                serializer.save()                
                return Response(ImageModel.objects.get(id=serializer.data['id']).image, content_type="image/png")
        return Response(data={"detail": "Serializer Error"})

By using the above code, I didn't get neither a valid image (it returns one small square box like image) nor an error
Hope someone can help ,Thanks

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I had the same issue and spent hours on it and I came up with a solution. Here's how you do it:

1. Create Custom Renderers

At first, you need to create something called custom renderers. Here's the link to the REST Framework's Renderers Documentation if you wanna know more about what renderers are and how to make custom renderers. In this case, we'll have to make custom renderers for .jpg and .png files. For this, I would suggest you create a file called custom_renderers.py and copy the following code into it:

custom_renderers.py

from rest_framework import renderers

class JPEGRenderer(renderers.BaseRenderer):
    media_type = 'image/jpeg'
    format = 'jpg'
    charset = None
    render_style = 'binary'

    def render(self, data, media_type=None, renderer_context=None):
        return data

class PNGRenderer(renderers.BaseRenderer):
    media_type = 'image/png'
    format = 'png'
    charset = None
    render_style = 'binary'

    def render(self, data, media_type=None, renderer_context=None):
        return data

2. Import the renderers and include them in your view by

After this, you've got to import the renders that you've just made and include them in your view within the attribute renderer_classes = [JPEGRenderer, PNGRenderer] if you are using class-based views (or if you are using method-based views, you've got to include them under the decorator @renderer_classes())

3. The rest of your view and the return statement

If you're serving an image or any kind of in your view, you've got to first open the image or the file by using .open() next to the image object that you've received as a response field of your query, and then use a FileWrapper() to wrap the image before you send it (The reason I was getting a small black box in the response just like you was that I had not opened the image before sending it and also hadn't used a FileWrapper()). So, your response goes like - return Response(FileWrapper(ImageModel.objects.get(id=serializer.data['id'])['image'].open())

I did not specify the return type as the return type was automatically determined in my case. Therefore, your views.py will finally be like:

## All the other necessary imports

from path.to.custom_renderers import JPEGRenderer, PNGRenderer
from wsgiref.util import FileWrapper

#Also, I think this should rather be ImageDownloadView as the client would be downloading the image
class ImageUploadView(viewsets.ModelViewSet):
    renderer_classes = [JPEGRenderer, PNGRenderer]

    queryset = ImageModel.objects.all()
    serializer_class = ImageSerializer

    def create(self, request, *args, **kwargs):
        userID = (request.data.get('userID'))
        serializer = self.get_serializer(data=request.data)
        if not UserModel.objects.filter(id=userID).exists():
            return Response(data={"detail": "Invalid UserID"})
        else:
            if serializer.is_valid():
                serializer.save()                
                return Response(FileWrapper(ImageModel.objects.get(id=serializer.data['id'])['image'].open())
                # You can also specify the content_type in your response
        return Response(data={"detail": "Serializer Error"})

Cheers!!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...