How can I code to get more than One value from checkbox? (Revised Version)

Steve Holden steve at holdenweb.com
Tue Oct 5 12:47:51 EDT 2004


Shufen wrote:
 > Hi,
 >
 > Sorry I know this is kinda of long, but please give me a helping hand
 > if you understand what I'm looking for.
 >
Sure, I have a minute ...

 > The following attached is my revised version of my code. I added some
 > stuffs into it and now it can really run - error (I supposed my method
 > is wrong again, but I hope my idea is there).
 >
Well, that's obviously an advantage: it's easier to say what's wrong
with something that does run, because you can say "instead of doing this
I want it to do that ..." and so on.

 > This is what is I have:
 > I have a bunch of stuffs in a database table named
 > "shot_descriptions".
 >
 > And this is what I wanna my page to do:
 > The columns of this table consists of project name, date, shot number,
 > notes and etc. And these fields are the stuffs that I wanna to present
 > them in checkboxes form so that the user can select the number of
 > information they wanna to see in the results (output). And a textbox
 > for user to key in a specific shot number in order to perform a
 > search. So, if there is no input in the shot no textbox, an error msg
 > will show (this is one of the part that is not working now, please
 > help). I wanna to display the output in a table form and I'm currently
 > using dictionary to help me with this task. But I'm wondering is there
 > a better way to show it? I mean other than dictionary, how can I code
 > it so that the results will display nicely in a html type of table
 > with columns and rows instead of key: blah blah and value: blah blah.
 > If someone can help me on this part, it will be very nice, cos I'm
 > concern about the presentation of the output too.
 >
Clearly if you are prepared to display the output in a table you are 
prepared to see information about multiple shots as the result of a 
single query, no? Otherwise the table would just have one row in it 
(plus headings, of course, so it wouldn't be a complete waste of time).

But your search doesn't seem to allow any ways of requesting more than 
one shot (like a list of shot numbers, or whatever), so I suspect I may 
be misunderstanding here.

Be that as it may, if we formulate a correct answer for a query result 
containing only one row, it should be possible to generalize it by 
putting the code that formats the data row of the table into a loop that 
iterates over multiple rows. So let's start with the single-row case.

 > Revised Version:
 > What I did is include a section where it will display an error msg
 > when no input is given. Besides, my code (earlier version) displayed
 > results in a repeated loop form when there is more than a tick in the
 > checkboxes.
 >
 > It will show somthing like this:
 > You entered Shot Number: xxxx
 >
 > key: xxxx   value: xxxx
 >
 > You entered Shot Number: xxxx
 >
 > key: xxxx   value: xxxx
 >
 > And it just went on....depending the number of ticks.
 >
 > Thus, in this revised version, I separated into 2 conditions.
 > Condition 1 taking care of more than one input and Condition 2 taking
 > care of only ONE input. But somehow, there is error in this code and I
 > suspected I did something very wrong again so please help me. I wonder
 > if there is any way to display the results in a nice table form for
 > Input that is more than ONE?
 >
Well, wouldn't it make more sense to show the results like

Shot #    Field 1     Field 2     ...     Field N
   23      value 1     value 2     ...     value N

In other words, vary the number of COLUMNS according to the requested 
attributes?

Also it's often helpful to write your loops so that "one" is not a 
special case, it's just what happens when you only go through the loop once.

 > Any help is very very much appreciated.
 >
 > I hope that will be someone responding to this as I took a long time
 > to figure out this revised code (I'm not good in programming - new)
 > and of cos to write this msg.
 >
I'm not able to follow things fully at present due to limited 
connectivity, but I hope I'm not just repeating what I know many other 
c.l.py readers are capable of articulating.

 > Thanks for any help.
 >
 > Shufen
 >
 >
 > 
###############################################################################
 > #!/usr/bin/env python
 > #Author: Chong Soo Fern
 > #Created on: 30/09/04
 > #Modified on: 02/10/04
 > #Help from Lee Harr, Danny Yoo and Steve - Python Tutor
 >
 > import cgi, os, sys, string
 > import cgitb; cgitb.enable()
 > import pg
 >
 > def form():
 >     print """<form method="post" action="">
 >            <table border="0" width="750" cellspacing="2"
 > cellpadding="2">
 >            <tr><td width="150" align="left">
 >            <input type=checkbox name="qtype" value="*" checked
 > />All</td>
 >            <td width="150" align="left">
 >            <input type=checkbox name="qtype" value="project"
 > />Project</td>
 >            <td width="150" align="left">
 >            <input type=checkbox name="qtype" value="notes"
 > />Notes</td>
 >            <td width="150" align="left">
 >            <input type=checkbox name="qtype" value="date_string"
 > />Date</td>
 >            </table>
 >
 >          <p>Search by shot number:<br>
 >          <input type=text name="shot_no" value="" tabindex="1" />
 >          <input type="submit" value="SEARCH" tabindex="2" />
 >          <input type="reset" value="RESET" tabindex="3" /><br />
 >          </form>"""
 >
 >
 > if __name__ == "__main__":
 >
 >     print "Content-Type: text/html\n\n"
 >     print "<head><title>Quick Search using Run
 > No</title></head><body>"
 >
 >     sys.stderr = sys.stdout
 >     data = cgi.FieldStorage()
 >
 >     #Get the shot_no first, followed by each value of the checkboxes.
 >     shot_no = data.getfirst("shot_no", "")
 >     qtype = data.getvalue("qtype")
 >
 >
 >     #I wanna to show the error msg if no input is given.
 >     if not (data.has_key("qtype") and data.has_key("shot_no")):
 >         print "You have not select an option!\n"
 >         print "Please tick at least one checkbox provided!\n"
 >         print "You have no enter a shot number\n!"
 >         print "Please type a in shot number in order to perform a
 > search\n!"
 >
Note that the code above needs HTML markup in the values you print - you 
send a "Content-Type:" header value of "text/html", so your browser will 
just jam all the words together unless you really send it HTML.

 >         #I don't know why this function kept showing error... please
 > advice
 >         #Error: SyntaxError: 'return' outside function
 >         return form()
 >
It's complaining because you have asked it to execute a "return" 
statement where there hasn't been a function called (which is pretty 
much what the error message says). Since you want to send the form to 
the browser, what you probably want here is just to call the form:

	form()

- particularly since the form() function doesn't return a value anyway, 
it just sends stuff to the output.

 >     if isinstance(qtype, list):
 >
I still don;t think you should be doing this, but the problem is that 
the old-style CGI interface code makes it hard not to. If you do

	for i in data.getvalue("qtype"):

when there's only one qtype, you end up iterating over the characters of 
the value (I suppose), or certainly something else equally unhelpful. 
That's why the "Higher-level interface" was bolted on. The cgi module is 
creaking under its own weight, by the way, and doesn't necessarily 
represent the best way to handle web interactions, but let's ignore that 
for now ...

 >         # Conditon 1: The user selected more than one qtype.
 >         # Display the results in one way, different from condition 2.
 >
 >         print "You entered Shot Number:", shot_no
 >
 >         #Will take care of the security problems later...
 >         #Defined a username and connect to the database...
 >         username = os.environ.get('USER')
 >         if username == "None":
 >             username = "apache"
 >
 >         db = pg.connect("moncdata", user=username, passwd=None)
 >         query = """SELECT %s FROM shot_descriptions WHERE
 > shot_number=%s""" % (qtype, shot_no)
 >         qresult = db.query(query)
 >         listOfResults = qresult.dictresult()
 >         print listOfResults
 >
 >         db.close()
 >
 >     else:
 >
 >         # Condition 2: The user selected only ONE qtype.
 >         # Display the results in another way.
 >         # I don't want each qtype to showed in sort of a repeated
 > results loop way.
 >
 >         print "You entered Shot Number:", shot_no
 >
 >         #Will take care of the security problems later...
 >         #Defined a username and connect to the database...
 >         username = os.environ.get('USER')
 >         if username == "None":
 >             username = "apache"
 >
 >         db = pg.connect("moncdata", user=username, passwd=None)
 >         query = """SELECT %s FROM shot_descriptions WHERE
 > shot_number=%s""" % (qtype, shot_no)
 >         qresult = db.query(query)
 >         listOfResults = qresult.dictresult()
 >         print """<p>Example of pulling the list of dictionary results
 > apart.</p>"""
 >         for record in listOfResults:
 >             print "<p><table>"
 >             for k in record.keys():
 >                 print '<tr>'
 >                 print '<td>key:</td> <td>', k, '</td>'
 >                 print '<br />'
 >                 print '<td>value:</td><td>', record[k], '</td>'
 >                 print '</tr>'
 >                 print '</table></p>'
 >
 >         db.close()
 >
 > print "</body></html>"
 >
 > 
###############################################################################

In essence, what I'd suggest is to buid a list of the field names you 
want, get the row from the database and then write out a table with the 
results in it.

The code would go something like this, but bear in mind this is 
untested, and only to give you the idea - you have demonstrated enough 
of a grasp of Python to put right any errors I might make ...

     fields = ["shotno"] + data.getlist("qtype")
     # this way we can treat shotno as "just another column"
     db = pg.cpnnect(...)
     query = """SELECT %s FROM shot_descriptions WHERE
                 shotno = %s""" % (", ".join(fields), shotno)
     # try running that in the interactive interpreter with
     # a hand-constructed fields list if you want to see
     # exactly what it does.
     qresult = db.query(query)
     listOfResults = qresult.dictresult()
     # Now for the interesting bits ...
     print """<table><tr>"""
     for f in fields:
         print "<td>%s</td>" % f
     # The only thing we can be sure of here is
     # that shotno WILL be the first (and maybe the
     # only) field on the result row
     print "</tr><tr>"
     for f in fields:
         print "<td>%s</td>" % qresult[f]
     # so each column header gets the right
     # result column underneath it
     print "</tr></table>"

A final db.close() and print "</body></html>" and TADAAAA!! the job is 
done. Or so the theory goes. You could actually set up a qdict by hand 
if necessary, just to see what the code prints. It *should* print a 
table with a column for each selected qtype field.

Does this help? Had to send this through the list as I can't connect to 
my news server from my current location.

regards
  Steve
-- 
http://www.holdenweb.com
http://pydish.holdenweb.com
Holden Web LLC +1 800 494 3119






More information about the Python-list mailing list