Search code examples
pythonajaxcherrypy

How to call a python script with ajax in cherrypy app


I am trying to get the output from a python script and put it into a table in the html of my cherrypy app.

Example app:

import string, os
import cherrypy

file_path = os.getcwd()

html = """<head>
<meta content="text/html; charset=ISO-8859-1"
http-equiv="content-type">
<title>CCMF</title>
<link rel='shortcut icon' type='image/x-icon' href='img/favicon.ico' />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>

<script>
    function b1() {
        var request = $.ajax({
            url: "b1.py",
            type: "POST",            
            dataType: "text"
        });
        request.done(function(msg) {
            $("#output").html(msg);          
        });
        request.fail(function(jqXHR, textStatus) {
            alert( "Request failed: " + textStatus );
        });
    }
</script>

</head>
<button onclick="b1()">call b1.py</button>
...
<td id = "output"; style="vertical-align: top; height: 90%; width: 100%;">
<--output goes here -->
</td>
...
</html>
"""
class ccmf(object):

    @cherrypy.expose
    def index(self):
    return html

if __name__ == '__main__':
    cherrypy.server.socket_host = "127.0.0.1"
    cherrypy.server.socket_port = 8084
    config = {
         "/img": {
             "tools.staticdir.on": True,
             "tools.staticdir.dir": os.path.join(file_path, "img"),
         }
    }
    cherrypy.tree.mount(ccmf(), "/", config=config)
    cherrypy.engine.start()
    cherrypy.engine.block()

and here's the example python script b1.py:

def b1():
    op = "ajax b1 pushed"
    print op
    return op

b1()

The ajax get's called but returns the failure alert. I have tried GET, POST, "text", "html", b1.py is in the same directory, no joy. All currently running on my local box.

Any hints greatly appreciated!


Solution

  • You are completely misunderstanding how modern, CherryPy's for instance, routing works. Unlike outdated approaches that were commonly employed with CGI and Apache's mod_* (mod_php, mod_python, etc.), where you directly point to the file containing the script with URL, modern routing is an application level activity.

    Your application receives all requests and dispatches them according to the established method. CherryPy in that sense has two major approaches: built-in object tree dispatcher and Routes adapter. For most simple and mid-level cases built-in dispatcher is fair enough.

    Basically it can look like this.

    app.py

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    
    import os
    
    import cherrypy
    from cherrypy.lib.static import serve_file
    
    
    path   = os.path.abspath(os.path.dirname(__file__))
    config = {
      'global' : {
        'server.socket_host' : '127.0.0.1',
        'server.socket_port' : 8080,
        'server.thread_pool' : 8
      }
    }
    
    class App:
    
      @cherrypy.expose
      def index(self):
        return serve_file(os.path.join(path, 'index.html')) 
    
      @cherrypy.expose
      @cherrypy.tools.json_out()
      def getData(self):
        return {
          'foo' : 'bar',
          'baz' : 'another one'
        }
    
    
    if __name__ == '__main__':
      cherrypy.quickstart(App(), '/', config)
    

    index.html

    <!DOCTYPE html>
    <html>
    <head>
    <meta http-equiv='content-type' content='text/html; charset=utf-8'>
    <title>CCMF</title>
    <script type='text/javascript' src='http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js'></script>
    <script type='text/javascript'>
      $(document).ready(function()
      {
        $('button').on('click', function()
        {
          var request = $.ajax({'url': '/getData'});
          request.done(function(response) 
          {
            $('#foo').text(response.foo);
            $('#baz').text(response.baz);
          });
          request.fail(function(jqXHR, textStatus) 
          {
            alert('Request failed: ' + textStatus);
          });
        })
      });
    </script>
    </head>
    <body>
      <button>make ajax call</button>
      <h1>Foo</h1>
      <div id='foo'></div>
      <h1>Baz</h1>
      <div id='baz'></div>
    </body>
    </html>