[Solved]-Django ajax error response best practice

18👍

If you return a response with a status code of 4xx or 5xx this is a an error and will trigger jQueries error handler. While it is certainly possible to simple return status 200 every time and use a “error” field in the JSON response (like suggested by dm03514) this is bad for two reasons:

  1. It violates good HTTP practice. There is a reason why there are plenty of error-codes defined

  2. You can’t use the fact that jQuery already has a error-Handler that lets you separate normal behavior from error handling.

Most of the time the error response will be much different from the non-error response So it simply makes no sense to put the handling of this messages in one piece of JS code. So, to sum things up, use a JSON response with status 200 for your normal responses and return a (appropriate!) 4xx/5xx response for errors. These can carry JSON payload, too, so your server side can add additional details about the error.

2👍

In my opinion:

  1. the second method is not acceptable.
  2. it will not failed since server will still send out a http response.
  3. Let me tell you what I do in my projects:

when my project starts, I always pre-add a module named errors in top of folder structure, firstly, I will write a base Exception class which inherits from Exception, then write out some common Exception classes like ObjectNotFound, ValidationError from my experience. When I think there should raise an exception in my code, I will use exceptions from this module, and when I find new kind of exception need to be handled, I will write a new exception in it.

Then it’s the work for how to handle them. As you are using Django, it very easy to catch exceptions through a middleware, you can write something like this:

from youproject import errors

# categorize your exceptions
400_ERRORS = (errors.ValidationError, errors.ParametersMissing, )
403_ERRORS = (errors.AuthenticationError, )
404_ERRORS = (errors.ObjectNotFound, errors.ResourceNotExist, )

class ExceptionHandleMiddleware(object):
    def process_exception(self, request, e):
        # set status_code by category of the exception you caught
        if isinstance(e, 400_ERRORS):
            status_code = 400
        elif isinstance(e, 403_ERRORS):
            status_code = 403
        elif isinstance(e, 404_ERRORS):
            status_code = 404
        else:
            # if the exception not belone to any one you expected,
            # or you just want the response to be 500
            status_code = 500
            # you can do something like write an error log or send report mail here
            logging.error(e)

        response_dict = {
            'status': 'error',
            # the format of error message determined by you base exception class
            'msg': str(e)
        }
        if settings.debug:
            # you can even get the traceback infomation when you are in debug mode
            response_dict['traceback'] = traceback.format_exc()

        # set header and return the response
        ....

The code above is a summary of how I do exception handle in my projects, in general, it’s about accurate exception controling, proper exception categorizing, and of course ‘Explicit is better than Implicit’ philosophy.

===UPDATE===
When it comes to how to deal with the corresponding responses in ajax, you can use the new feature in jquery1.5 statusCode:

$.ajax({
  statusCode: {
    404: function() {
      alert('page not found');
    }
  }
});

from jquery documentation:

A map of numeric HTTP codes and functions to be called when the
response has the corresponding code. For example, the following will
alert when the response status is a 404

👤Reorx

0👍

I can’t answer whether both methods are acceptable but can only tell you what I do. In my view I catch some specific/explicit errors such as:

  • Invalid or missing params in post
  • High level errors such as username already present in database (in a signup situation for e.g.)
  • All other system errors

I think if you categorize your errors as some specific errors that the user must know about and then everything else then your code will have at the most 2 or 3 return with error routes, which IMHO isn’t so bad.
I use JSON to return errors and my structure is usually such:

respons={}
response["error|ok"]
response["msg"]="User not found"
response["type"]=ERROR_TYPE # only applicable for errors

Obviously this is quite basic but hopefully gives you a general idea. I would recommend against letting the user see the system generated internal server error. That is horrible user experience, even for internal apps.

Hope this helps.

👤Sid

0👍

I would take neither of your suggested approaches. I would suggest something along the lines of what Sid said. Why would you not want to write error free code?

I would try to address all possible bugs and errors in the code I write at all times. This includes validating user input. With ajax i think it is important to send the messages back to the user. This is easily accomplished with json.

response_dict = {}
try:
   # do action that could cause an error
except ExpectedError as e:
   response_dict['success'] = False
   response_dict['message'] e.msg # or custom message
   return HttpResponse(json.dumps(repsonse_dict))

then in your ajax call back make sure the response is valid, if it is not alert the user of what they have done wrong. don’t leave them hanging you are making an app for them!

0👍

Use option 1 but not entirely the way you describe it, you should return a HttpResponse with status_code 200 indicating in the response content (using JSON or some text) that a validation error occurred, then, when you process the response on the client with JQuery just check for the response content and detect if there were validation errors.

Example of JSON string for the HttpResponse:

{"errors": "true", "messages": ["Error #1", "Error #2", "etc."]}

Option 2 is not a good practice because internal server errors happens when there is an uncaught exception that that was thrown by the server and commonly is unknown to the programmer.

Don’t use HTTP status codes to denote validation errors, that is not their purpose.

Leave a comment