Search code examples
pythonhtmlsqlitenullcherrypy

CherryPy web form: checkboxes produces error when unchecked


I'm trying to produce a simple web form using CherryPy in Python 3.5 (to compare with an sqlite3 database) which takes a few inputs of different types of data. When the checkboxes are left unticked, it produces an error as (i assume) there is no default null value; it is either 'on' or nonexistant. How can I change my form so that it autommatically sets empty boxes to 'None'? Here is the code (section):

class startScreen(object):
    @cherrypy.expose
    def index(self):
        return """<form method="post" action="search">
        Job Title:<br>
        <input type="text" name="title"><br>
        Employer name:<br>
        <input type="text" name="employer"><br>
        Minimum Starting Salary:<br>
        <input type="number" name="minsal"><br>
        Contract Hours Per Week:<br>
        <input type="number" name="hpwMin">
        <input type="number" name="hpwMax"><br>
        Start Date:<br>
        <input type="date" name="startDate"><br>
        <!--jobtype drop down menu--!>
        Contract Length (months):<br>
        <input type="number" name="CLMin">
        <input type="number" name="CLMax"><br>
        <!--qualifications list--!>
        <!--key skills list--!>
        Training Offered:<br>
        <input type="checkbox" name="training"><br>
        Expenses covered:<br>
        <input type="checkbox" name="expenses"><br>
        Job benefits:<br>
        <input type="checkbox" name="benefits"><br>
        Number of days annual holiday: <br>
        <input type="number" name="holiday"><br>
        Opportunities abroad:<br>
        <input type="checkbox" name="abroad"><br>
        Date posted: <br>
        <input type="date" name="datePosted"><br>


        <button type="submit">Submit</button>
        </form>

        """
    @cherrypy.expose #needed for every page
    def search(self, title, employer, minsal, hpwMin, hpwMax, startDate, CLMin, CLMax, training, expenses, benefits, holiday, abroad, datePosted):
        search.search.searchDBS(title, employer, minsal, hpwMin, hpwMax, startDate, CLMin, CLMax, training, expenses, benefits, holiday, abroad, datePosted)
        return "done"

This is the output on the webpage when the one tickbox is unchecked:

404 Not Found

Missing parameters: training

Traceback (most recent call last):
  File "C:\Users\Anna\AppData\Local\Programs\Python\Python35\lib\site-packages\cherrypy\_cpdispatch.py", line 60, in __call__
    return self.callable(*self.args, **self.kwargs)
TypeError: search() missing 1 required positional argument: 'training'

During handling of the above exception, another exception occurred:

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

Solution

  • That's the regular behavior of the html checkboxes, you can handle that with a default argument: training=None or use kwargs and look for the key.

    For the first option, your expose method would be:

    @cherrypy.expose #needed for every page
    def search(self, title, employer, minsal, hpwMin, hpwMax,
               startDate,  CLMin, CLMax, expenses,
               benefits, holiday, abroad, datePosted, training=None):
        # "training" will be None, if the checkbox is not set
        # you can verify with something like:
        # if training is None:
        #    ...
        search.search.searchDBS(
           title, employer, minsal, hpwMin, hpwMax,
           startDate, CLMin, CLMax, training, expenses,
           benefits, holiday, abroad, datePosted)
        return "done"
    

    Another alternative (better from my perspective, because those are a lot of parameters for a method, you can use the **params alternative:

    @cherrypy.expose #needed for every page
    def search(self, **params):
        fields = ['title', 'employer', 'minsal', 'hpwMin',
                  'hpwMax', 'startDate', 'CLMin', 'CLMax',
                  'training', 'expenses','benefits', 'holiday',
                  'abroad','datePosted']
        # the params.get, will try to get the value if the field
        # and if is not defined, then it will return None
        search.search.searchDBS(*[params.get(f, None) for f in fields])
        # alternative approach without passing specific fields
        #if 'training' not in params: 
        #    params['training'] = None
        #search.search.searchDBS(**params)
        return "done"