Search code examples
jquerypythonajaxcherrypy

Getting Data back from Python with Cherrypy and jQuery/AJAX


Unfortunately i dont get ajax to work properly with cherrypy. Here is my python code:

from mako.template import Template
from mako.lookup import TemplateLookup
import cherrypy
import os
import json

CURDIR = os.getcwd()

cherrypy.config.update({
    "tools.staticdir.root" : CURDIR,
    "tools.staticdir.dir" : "static",
    "tools.staticdir.on" : True
    })

# Loopuoobjekt für die Templates
tmplLookup = TemplateLookup(directories=['templates'])
# Liefert das Gerenderte Template zurück
def serve_template(templatename, **tmpl_vars):
    template = tmplLookup.get_template(templatename)
    return template.render(**tmpl_vars)

class Root(object):
    @cherrypy.expose
    def index(self):
        return serve_template("index.html")

    @cherrypy.expose
        def switch(self, id):
        print("Licht nr {} wurde geschaltet".format(id))
        cherrypy.response.headers["Content-Type"] = "application/json"
        return json.dumps({"text" : "schalter {} ".format(id)})

cherrypy.quickstart(Root())

and Here is my html template:

<html>
<head>
    <script src="jquery.js" type="text/javascript"></script>
    <script type="text/javascript">
    $(document).ready(function() {
        $("button").click(function() {
            $.ajax({
                url: "switch",
                type: "POST",
                data: {id: $(this).attr('id')},
                succes: function(response) {
                    $("#test").html(response);
                } 
            });
        });
    });
    </script>
</head>
<body>
    <h1>Hallo Haus!</h1>
    <button id=1>Licht 1</button> </br>
    <button id=2>Licht 2</button> </br>
    <button id=3>Licht 3</button> </br>
    <button id=4>Licht 4</button>

    <div id=test></div>

</body>
</html>

If i press one of those 4 buttons i get the right id printed in my console. The above example

return json.dumps({"text" : "schalter {} ".format(id)})

is written on the most toturials i found, but unfortunately this gives me an error:

[09/Apr/2014:15:36:57] HTTP Traceback (most recent call last):
File "C:\Python33\lib\site-packages\cherrypy-3.2.4-py3.3.egg\cherrypy\_cprequ
est.py", line 656, in respond
    response.body = self.handler()
  File "C:\Python33\lib\site-packages\cherrypy-3.2.4-py3.3.egg\cherrypy\_cprequ
est.py", line 814, in __set__
raise ValueError(self.unicode_err)
ValueError: Page handlers MUST return bytes. Use tools.encode if you wish to re
turn unicode.

So the data is succesfully send to cherrypy, but i did not get it back. Any help how to get this to work?


Solution

  • Try adding @cherrypy.tools.json_out() to your switch handler...

    import cherrypy
    import os
    import json
    
    CURDIR = os.getcwd()
    
    cherrypy.config.update({
        "tools.staticdir.dir" : CURDIR,
        "tools.staticdir.on" : True
        })
    
    # Loopuoobjekt für die Templates
    
    # Liefert das Gerenderte Template zurück
    class Root(object):
        @cherrypy.expose
        def index(self):
            return """<html>
    <head>
    <script src="jquery.js" type="text/javascript"></script>
    <script type="text/javascript">
    $(document).ready(function() {
        $("button").click(function() {
            $.ajax({
                url: "switch",
                type: "POST",
                data: {id: $(this).attr('id')},
                success: function(response) {
                    alert(response);
                    $("#test").html(response);
                } 
            });
        });
    });
    </script>
    </head>
    <body>
        <h1>Hallo Haus!</h1>
        <button id=1>Licht 1</button> </br>
        <button id=2>Licht 2</button> </br>
        <button id=3>Licht 3</button> </br>
        <button id=4>Licht 4</button>
    
        <div id=test></div>
    
    </body>
    </html>"""
    
        @cherrypy.expose
        @cherrypy.tools.json_out()
        def switch(self, id):
            print("Licht nr {} wurde geschaltet".format(id))
            return json.dumps({"text" : "schalter {} ".format(id)})
    
    cherrypy.quickstart(Root())
    

    Hope this helps!