ankush981
ankush981

Reputation: 5417

Why is json.dumps() a must in Flask?

(This is probably a dumb question, so please wear your stupidity shields!) I've been a PHP programmer and am now learning Python + Flask. I recently had to struggle a lot with posting data through AJAX and returning a response. Finally, the code that worked was:

@app.route('/save', methods=['POST'])
def save_subscriptions():
    if request.method == 'POST':
        sites = request.form.get('selected')
        print(sites)
        sites = sites[0:-1]        
        g.cursor.execute('UPDATE users SET sites = %s WHERE email = %s', [sites, session.get('email')])
        g.db.commit()
        return json.dumps({'status': 'success'})

If I change return json.dumps({'status': 'success'}) to return 1 I get an Exception that int is not callable. First of all, I don't understand who is trying to call that int and why? Secondly, in PHP, it was frequently possible to just echo 1; and this would become the AJAX response. Why doesn't return 1 work in Flask, then?

Upvotes: 6

Views: 1570

Answers (1)

alecxe
alecxe

Reputation: 474031

The logic behind what should be returned by Flask views is described in the docs in detail:

The return value from a view function is automatically converted into a response object for you. If the return value is a string it’s converted into a response object with the string as response body, an 200 OK error code and a text/html mimetype. The logic that Flask applies to converting return values into response objects is as follows:

  • If a response object of the correct type is returned it’s directly returned from the view.

  • If it’s a string, a response object is created with that data and the default parameters.

  • If a tuple is returned the items in the tuple can provide extra information. Such tuples have to be in the form (response, status, headers) where at least one item has to be in the tuple. The status value will override the status code and headers can be a list or dictionary of additional header values.

  • If none of that works, Flask will assume the return value is a valid WSGI application and convert that into a response object.

In your case, integer 1 is returned - Flask applies the last rule and tries to convert it into a response object and fails. Internally, make_response() method is called which, in case of an integer, would call force_type() method of a werkzeug.Response class which would eventually fail creating an instance of a BaseResponse class when trying to instantiate a WSGI app:

app_rv = app(environ, start_response)

where app in your case is integer 1.

Upvotes: 8

Related Questions