0

I have a piece of code in a Django REST framework that looks like the following. It works if the request arguments are valid, but if I specify a non-valid search keyword, the browser returns an empty python file with length of 0 bytes instead of an HTML error code. What am I doing wrong with respect to error catching?

from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.renderers import JSONRenderer, StaticHTMLRenderer
from rest_framework.exceptions import ParseError

class GetDataseriesId(APIView):
    renderer_classes = (JSONRenderer, StaticHTMLRenderer)

    def get(self, request, format=None):
        # check format keyword and overrule default rendering format
        if 'format' in request.query_params:
            request.accepted_renderer.format = request.query_params['format']
        # build keyword arguments  (left out for clarity)
        search_dict = {'station_name':'Example'}
        # render query
        try:
            res = DataseriesIdSerializer(**search_dict)
        except Exception as e:
            raise ParseError("Malformed REST service request.\nDetail: %s", e)
        return Response(res.data)

The server error log reports the psycopsg2 error which I wanted to generate:

[Tue Apr 19 13:09:53 2016] [error] Error when executing query SELECT [...] 
[Tue Apr 19 13:09:53 2016] [error] column s.station_itgd does not exist 
This is indeed the error I wanted to generate. 

The issue is that I thought my code would capture this error and then generate a proper eror view. But this doesn't happen. I am aware that catching any Exception is not a good practice - this is just the first step. Once I get the response to work I will analyze which errors may occur and improve this part.

5
  • are you quite sure it's a python file and not an empy html file? Commented Apr 19, 2016 at 11:40
  • well, this is what the browser message says. It brings up the file download window and asks me if I want to save a python file. The suggested name is N8UhopSP.py -- I am completely at loss where I shall start looking for what may go wrong. Commented Apr 19, 2016 at 13:11
  • anything in the logs? Commented Apr 19, 2016 at 13:12
  • Well, it does show the underlying error, which comes from psycop: [Tue Apr 19 13:09:53 2016] [error] Error when executing query SELECT [...] [Tue Apr 19 13:09:53 2016] [error] column s.station_itgd does not exist This is indeed the error I wanted to generate. I had thought that this should be caught by my try - except block and therefore transformed into a proper error view. But apparently this is not happening. Commented Apr 19, 2016 at 13:32
  • Well it might possibly be relevent and might be usefull if you add it to the question. Also worth noting that catch all exceptions of the type that you have in your code snippet does lead to troublesome situation. Better to catch more specific exceptions and add a catch all only in case you really can't predict something. Commented Apr 19, 2016 at 13:47

2 Answers 2

1

In a DRF view, you are always supposed to return a Response object. You could, instead of raising a ParseError, from rest_framework import status return Response({'detail':"Your error message"}, status=status.HTTP_400_BAD_REQUEST), Any uncatched exception will simply return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR)

Sign up to request clarification or add additional context in comments.

1 Comment

The documentation () explicitly says: "REST framework's views handle various exceptions, and deal with returning appropriate error responses. [...] In each case, REST framework will return a response with an appropriate status code and content-type. The body of the response will include any additional details regarding the nature of the error." I understand this as permission to raise such exceptions (subclasses of APIException) and that the DRF automatically converts this into a Response. Is this not so?
0

OK - I found part of the solution: I was actually catching the DatabaseError earlier without raising it again, so my serializer returned an empty data object. It is still puzzling though that the DRF ends up letting you save an empty python file. To me this is unexpected behaviour.

But to confirm: raising an exception that is a subclass of APIException does work and generates the desired 400 Bad Request response.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.