1

I'm using Django 2.x and DRF

I have a view which returns the binary data in different formats like pdf, eps, etc.

To return binary response, I have set the renderer_classes property and my view is

class DownloadQRCode(APIView):
    renderer_classes = (PdfFileRenderer, EPSRenderer,)

    def post(self, request):
        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)

        name = serializer.validated_data.get('name')
        data = serializer.validated_data.get('data')

        mimetype = None

        if data and name:

            imgarr = name.rsplit('.', 1)

            if len(imgarr) == 2:
                name, format = imgarr

                if format == 'pdf':
                    data = str(unquote(data, encoding='utf-8'))
                    data, mimetype = generate_data_cairo(data, format)
                if format == 'eps':
                    data = str(unquote(data, encoding='utf-8'))
                    data, mimetype = svg_2_eps(data)

                if data and mimetype:

                    response = Response(data=data, content_type=mimetype)

                    response['Content-Disposition'] = 'attachment; filename=%s' % "-".join(name.split())

                    return response
                else:
                    return Response(status=status.HTTP_400_BAD_REQUEST, data='Either data or mime type was missing')
            else:
                return Response(status=status.HTTP_400_BAD_REQUEST, data='filename does not contain formatInfo')
        else:
            return Response(status=status.HTTP_400_BAD_REQUEST)

I have two renderer_classes

PdfFileRenderer

class PdfFileRenderer(BaseRenderer):
    media_type = 'application/octet-stream'
    format = None
    charset = None
    render_style = 'binary'

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

and EPSRenderer

class EPSRenderer(BaseRenderer):
    media_type = 'image/eps'
    format = None
    charset = 'utf-8'
    render_style = 'binary'

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

Using any one of them is working fine for that file type. But I want to use both so that appropriate renderer can be used depending on the file requested.

But, this is giving error and only first in the set is working.

Anuj TBE
  • 9,198
  • 27
  • 136
  • 285
  • 1
    Could you please share your error (traceback)? It should definitely be possible see: https://www.django-rest-framework.org/api-guide/renderers/#ordering-of-renderer-classes – matt.LLVW Nov 15 '19 at 08:29
  • 2
    What in the docs leads you to believe that you can vary the renderer by setting the content_type in the response? – Daniel Roseman Nov 15 '19 at 08:37
  • 1
    Renderer class is chosen based on request's `Accept` header via content negotiation. Send appropriate header from client side to select correct renderer class. You can read more about it [here](https://www.django-rest-framework.org/api-guide/content-negotiation/) – Nafees Anwar Nov 15 '19 at 09:00

1 Answers1

0

Agree with @Nafees

Got it resolved by overriding get_renderer() method.

def get_renderer(self):

    imgarr = name.rsplit('.', 1)
    name, format = imgarr

    if format == 'pdf':
       return [BinaryRenderer()]
    if format == 'eps':
       return [EPSRenderer()]

    return super().get_renderer()
Anuj TBE
  • 9,198
  • 27
  • 136
  • 285