16

I have the following jquery code:

$.ajax({
    type: 'POST',
    url: url,
    data: data,
    dataType: 'json',
    statusCode: {
        200: function (data, textStatus, jqXHR) {
                console.log(data);
            },
        201: function (data, textStatus, jqXHR) {
                 log(data);
            },
        400: function(data, textStatus, jqXHR) {
                log(data);
            },
    },
});

the 400 is used when the validation in backend (Pyramid) fails. Now from Pyramid how do I return HTTPBadRequest() response together with a json data that contains the errors of validation? I tried something like:

response = HTTPBadRequest(body=str(error_dict)))
response.content_type = 'application/json'
return response

But when I inspect in firebug it returns 400 (Bad Request) which is good but it never parses the json response from data.responseText above.

Marconi
  • 3,601
  • 4
  • 46
  • 72

3 Answers3

30

Well you should probably start off by serializing the error_dict using a json library.

import json
out = json.dumps(error_dict)

Given that you don't give any context on how your view is setup, I can only show you how I would do it:

@view_config(route_name='some_route', renderer='json')
def myview(request):
    if #stuff fails to validate:
        error_dict = # the dict
        request.response.status = 400
        return {'errors': error_dict}

    return {
        # valid data
    }

If you want to create the response yourself, then:

response = HTTPBadRequest()
response.body = json.dumps(error_dict)
response.content_type = 'application/json'
return response

To debug the issue, stop going based off of whether jQuery works and look at the requests yourself to determine if Pyramid is operating correctly, or if it is something else that's going on.

curl -i <url>

Or even just open up the debugger in the browser to look at what is being returned in the response.

CppLearner
  • 16,273
  • 32
  • 108
  • 163
Michael Merickel
  • 23,153
  • 3
  • 54
  • 70
  • Thanks, I've figured it using the same way too. :) – Marconi Jul 22 '11 at 04:13
  • if your are using a json renderer and still wants to return a httpexception you must use `raise response` instead of `return response` – Francisco Puga Mar 04 '15 at 11:17
  • Just found this --bump-- and I think at least in the current version, instead of `request.response.status = 400` it should be `request.response.status_int = 400` yes? – Still.Tony Jun 23 '15 at 17:19
  • Never mind, apparently when setting `.status` to an integer, Pyramid automatically fills the text in for you. http://stackoverflow.com/a/9815676/2043621 Wish I could find that in the docs – Still.Tony Jun 23 '15 at 19:21
3

I found a simple way to do it more generic then the accepted answer, I got it with this code

I include exception_response in my view

from pyramid.httpexceptions import exception_response

I raise the 400 exception where I need to

 raise exception_response(400)

In my exceptions script, I trap all exceptions to return generic json and I trap 400 to return a specific json

from pyramid.view import exception_view_config

from pyramid.httpexceptions import (
    HTTPException,
    HTTPBadRequest
)


@exception_view_config(HTTPException, renderer='json')
def exc_view_exception(message, request):
    return {'error': str(message)}


@exception_view_config(HTTPBadRequest, renderer='json')
# Exception 400 bad request
def exc_view_bad_request(message, request):
    body = {
        "message": str(message),
        "status": 400
    }
    request.response.status = 400
    return body
Michael
  • 1,063
  • 14
  • 32
0

You can change response status code like this: request.response.status_code = 400. Following examle is working for me

@view_config(route_name='qiwiSearch', request_method='GET', renderer='json')
def qiwiSearchGet(request):
    schema = SchemaQiwiSearchParams()
    try:
        params = schema.deserialize(request.GET)
    except colander.Invalid, e:
        errors = e.asdict()
        request.response.status_code = 400
        return dict(code=400, status='error', message=unicode(errors))

    log.debug(u'qiwiSearchGet: %s' % params)
    return dict(code=200, status='success', message='', data=[1,2,3])