Search code examples
javascriptpythonjsonajaxcherrypy

Cherrypy - reciving JSON data 404, 'Missing parameters'


I'm making my own site from scratch using Cherrypy Postgresql. I am a beginner with Python and Javascript but I am very enthusiastic about learning those two programming languages.


What I am trying to achieve right now is to fill up HTML form -> Send data using JSON by AJAX -> Define Rights for a visitor -> and redirect to index after its all done.


I am fighting with this error for days because I cannot find an example on the internet how to send data in python by AJAX using JSON


As I said I am a beginner so point all bad behaviours in code I am making, please :)

Traceback (most recent call last):
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\cherrypy\_cpdispatch.py", line 60, in __call__
    return self.callable(*self.args, **self.kwargs)
TypeError: login() missing 1 required positional argument: 'dataString'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\cherrypy\_cprequest.py", line 670, in respond
    response.body = self.handler()
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\cherrypy\lib\encoding.py", line 221, in __call__
    self.body = self.oldhandler(*args, **kwargs)
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\cherrypy\_cpdispatch.py", line 66, in __call__
    raise sys.exc_info()[1]
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\cherrypy\_cpdispatch.py", line 64, in __call__
    test_callable_spec(self.callable, self.args, self.kwargs)
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\cherrypy\_cpdispatch.py", line 163, in test_callable_spec
    raise cherrypy.HTTPError(404, message=message)
cherrypy._cperror.HTTPError: (404, 'Missing parameters: dataString')

Cherrypy engine printout

[12/Jun/2017:13:44:03]  Testing database is disabled, deleting test users... skipping...
[12/Jun/2017:13:44:03]  ====== INIT SQL ======
[12/Jun/2017:13:44:03]  Connecting to PostgreSQL database...
[12/Jun/2017:13:44:03]  Testing engine is enabled, adding record...
[12/Jun/2017:13:44:03]  ====== INIT SRV ======
[12/Jun/2017:13:44:03] ENGINE Bus STARTING
CherryPy Checker:
The Application mounted at '' has an empty config.

[12/Jun/2017:13:44:03] ENGINE Started monitor thread 'Autoreloader'.
[12/Jun/2017:13:44:03] ENGINE Started monitor thread '_TimeoutMonitor'.
C:\Program Files (x86)\Python36-32\lib\site-packages\cherrypy\process\servers.py:411: UserWarning: Unable to verify that the server is bound on 8080
  warnings.warn(msg)
[12/Jun/2017:13:44:08] ENGINE Serving on http://0.0.0.0:8080
[12/Jun/2017:13:44:08] ENGINE Bus STARTED

Python Login method

class Root(object):
    exposed = True

    @cherrypy.expose
    # @cherrypy.tools.json_out()
    @cherrypy.tools.json_in()
    @cherrypy.tools.accept(media='application/json')
    def login(self, dataString):
        # cherrypy.request.method == "POST":
        self.addHeader()
        db = config()
        conn = psycopg2.connect(**db)
        cur = conn.cursor()
        is_logged_in = None
        bad_username = None
        bad_password = None
        json.load(dataString)
        # input_json = cherrypy.request.json()
        # dataString = input_json["dataString"]
        # - Login
        username_input = dataString[0]
        if username_input == cur.execute("SELECT username FROM users WHERE username = %s;", (username_input)):
            username_password = dataString[1]
            if username_password == cur.execute("SELECT password FROM users WHERE password = %s;", (username_password)):
                return is_logged_in
            else:
                return bad_password
        else:
            return bad_username

    @cherrypy.expose
    def index(self):
        self.addHeader()
        return "ok"

Javascript .js override submit function

$("#myForm").submit(function(){
    var dataString = [];
    dataString.login = $("#login").val();
    dataString.password = $("#password").val();

    $.ajax({
      type: 'POST',
      url: 'http://0.0.0.0:8080/login',
      data: JSON.stringify(dataString),
      contentType: 'application/json',
      dataType: 'json',
      success: function(response) {
          console.log(response);
      },
      error: function(response) {
          console.log(response);
      }
    });
});

HTML File

<!DOCTYPE html>
<html>
  <head>
    <link href="style.css" rel="stylesheet">
    <script src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
    <script src="example.js"></script>
  </head>
<body>
<div class="login-page">
  <div class="form">
      <form action="/process_form/" method="post">
      <!-- id="myForm" class="login-form"> -->
        <input type="text" name="login" id="login" placeholder="login"/>
        <input type="password" name="password" id="password" placeholder="password"/>
        <button form="myForm" type="submit">Login</button>
        <p class="message">Not registered? <a href="#">Create an account</a></p>
      </form>
  </div>
</div>
</body>
</html>

Solution

  • The AJAX data you'll receive in in your login function is not contained in the parameter dataString (actually, you will not get any parameter) but in cherrypy.request.json.

    Thus you should change your login function as follows:

    @cherrypy.expose
    @cherrypy.tools.json_in()
    def login(self):
        json_obj = cherrypy.request.json
        ...
    

    Note that you will receive an actual object (dict / list) based on the AJAX parameters, not a string.

    Another note: cherrypy.request.json is only filled if you've set the decorator @cherrypy.tools.json_in() (as you already did).