web-dev-qa-db-fra.com

Python Flask, TypeError: l'objet 'dict' n'est pas appelable

Ayant un problème qui semble être commun pourtant j'ai fait mes recherches et ne le vois pas être recréé exactement où Lorsque j'imprime json.loads(rety.text), je vois la sortie dont j'ai besoin. Pourtant, lorsque j'appelle retour, cela me montre cette erreur. Des idées? L'aide est grandement appréciée et merci. J'utilise la fiole MethodHandler.

class MHandler(MethodView):
    def get(self):
        handle = ''
        tweetnum = 100

        consumer_token = '' 
        consumer_secret = ''
        access_token = '-'
        access_secret = ''

        auth = tweepy.OAuthHandler(consumer_token,consumer_secret)
        auth.set_access_token(access_token,access_secret)

        api  = tweepy.API(auth)

        statuses = api.user_timeline(screen_name=handle,
                          count= tweetnum,
                          include_rts=False)

        pi_content_items_array = map(convert_status_to_pi_content_item, statuses)
        pi_content_items = { 'contentItems' : pi_content_items_array }

        saveFile = open("static/public/text/en.txt",'a') 
        for s in pi_content_items_array: 
            stat = s['content'].encode('utf-8')
            print stat

            trat = ''.join(i for i in stat if ord(i)<128)
            print trat
            saveFile.write(trat.encode('utf-8')+'\n'+'\n')

        try:
            contentFile = open("static/public/text/en.txt", "r")
            fr = contentFile.read()
        except Exception as e:
            print "ERROR: couldn't read text file: %s" % e
        finally:
            contentFile.close()
        return lookup.get_template("newin.html").render(content=fr) 

    def post(self):
        try:
            contentFile = open("static/public/text/en.txt", "r")
            fd = contentFile.read()
        except Exception as e:
            print "ERROR: couldn't read text file: %s" % e
        finally:
                contentFile.close()
        rety = requests.post('https://gateway.watsonplatform.net/personality-insights/api/v2/profile', 
                auth=('---', ''),
                headers = {"content-type": "text/plain"},
                data=fd
            )

        print json.loads(rety.text)
        return json.loads(rety.text)


    user_view = MHandler.as_view('user_api')
    app.add_url_rule('/results2', view_func=user_view, methods=['GET',])
    app.add_url_rule('/results2', view_func=user_view, methods=['POST',])

Voici le traçage (n'oubliez pas que les résultats sont en train d'être imprimés ci-dessus):

Traceback (most recent call last):
  File "/Users/RZB/anaconda/lib/python2.7/site-packages/flask/app.py", line 1836, in __call__
    return self.wsgi_app(environ, start_response)
  File "/Users/RZB/anaconda/lib/python2.7/site-packages/flask/app.py", line 1820, in wsgi_app
    response = self.make_response(self.handle_exception(e))
  File "/Users/RZB/anaconda/lib/python2.7/site-packages/flask/app.py", line 1403, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/Users/RZB/anaconda/lib/python2.7/site-packages/flask/app.py", line 1817, in wsgi_app
    response = self.full_dispatch_request()
  File "/Users/RZB/anaconda/lib/python2.7/site-packages/flask/app.py", line 1478, in full_dispatch_request
    response = self.make_response(rv)
  File "/Users/RZB/anaconda/lib/python2.7/site-packages/flask/app.py", line 1577, in make_response
    rv = self.response_class.force_type(rv, request.environ)
  File "/Users/RZB/anaconda/lib/python2.7/site-packages/werkzeug/wrappers.py", line 841, in force_type
    response = BaseResponse(*_run_wsgi_app(response, environ))
  File "/Users/RZB/anaconda/lib/python2.7/site-packages/werkzeug/test.py", line 867, in run_wsgi_app
    app_rv = app(environ, start_response)
30
puhtiprince

Flask s'attend à ce que les vues renvoient un objet semblable à une réponse. Ceci signifie une Response, une chaîne ou un tuple décrivant le corps, le code et les en-têtes. Vous retournez un dict, qui n'est pas une de ces choses. Puisque vous retournez du JSON, retournez une réponse avec la chaîne JSON dans le corps et un type de contenu de application/json.

return app.response_class(rety.content, content_type='application/json')

Dans votre exemple, vous avez déjà une chaîne JSON, le contenu renvoyé par la demande que vous avez faite. Toutefois, si vous souhaitez convertir une structure Python en une réponse JSON, utilisez jsonify:

data = {'name': 'davidism'}
return jsonify(data)

En coulisse, Flask est une application WSGI, qui s'attend à transmettre des objets appelables. C'est pourquoi vous obtenez cette erreur spécifique: un dict n'est pas appelable et Flask ne sait pas comment le transformer.

50
davidism

Utilisez la fonction Flask.jsonify pour renvoyer les données.

from flask import jsonify 
# ...
return jsonify(data)
10
Sahil Shah

Si vous renvoyez un tuple data, status, headers à partir d'une vue Flask, Flask ignore actuellement le code d'état et l'en-tête content_type lorsque les données sont déjà un objet de réponse, comme ce que jsonify renvoie.

Cela ne définit pas l'en-tête content-type:

headers = {
    "Content-Type": "application/octet-stream",
    "Content-Disposition": "attachment; filename=foobar.json"
}
return jsonify({"foo": "bar"}), 200, headers

Utilisez plutôt flask.json.dumps pour générer les données (c'est-à-dire ce que jsonfiy utilise en interne).

from flask import json

headers = {
    "Content-Type": "application/octet-stream",
    "Content-Disposition": "attachment; filename=foobar.json"
}
return json.dumps({"foo": "bar"}), 200, headers

Ou travaillez avec l'objet de réponse:

response = jsonify({"foo": "bar"})
response.headers.set("Content-Type", "application/octet-stream")
return response

Cependant, si vous voulez littéralement faire ce que ces exemples montrent et servir les données JSON sous forme de téléchargement, utilisez plutôt send_file.

from io import BytesIO
from flask import json
data = BytesIO(json.dumps(data))
return send_file(data, mimetype="application/json", as_attachment=True, attachment_filename="data.json")
3
firelynx

Au lieu d'essayer de jsonifier la réponse, cela a fonctionné.

return response.content
0
l3o