diff options
-rw-r--r-- | MANIFEST.in | 1 | ||||
-rw-r--r-- | cherrypy/lib/defaultformmask.py | 97 | ||||
-rw-r--r-- | cherrypy/lib/form.py | 124 | ||||
-rw-r--r-- | setup.py | 2 |
4 files changed, 222 insertions, 2 deletions
diff --git a/MANIFEST.in b/MANIFEST.in index 555a67ba..c17f2305 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,3 @@ include CHANGELOG.txt include CHERRYPYTEAM.txt include *.conf -include *.py diff --git a/cherrypy/lib/defaultformmask.py b/cherrypy/lib/defaultformmask.py new file mode 100644 index 00000000..1eab2c75 --- /dev/null +++ b/cherrypy/lib/defaultformmask.py @@ -0,0 +1,97 @@ +"""
+Copyright (c) 2004, CherryPy Team (team@cherrypy.org)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the CherryPy Team nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+"""
+
+"""
+Default mask for the form.py module
+"""
+
+def defaultMask(field):
+ res="<tr><td valign=top>%s</td>"%field.label
+ if field.typ=='text':
+ res+='<td><input name="%s" type=text value="%s" size=%s></td>'%(field.name, field.currentValue, field.size)
+ elif field.typ=='forced':
+ res+='<td><input name="%s" type=hidden value="%s">%s</td>'%(field.name, field.currentValue, field.currentValue)
+ elif field.typ=='password':
+ res+='<td><input name="%s" type=password value="%s"></td>'%(field.name, field.currentValue)
+ elif field.typ=='select':
+ res+='<td><select name="%s">'%field.name
+ for option in field.optionList:
+ if type(option)==type(()):
+ optionId, optionLabel=option
+ if optionId==field.currentValue or str(optionId)==field.currentValue: res+="<option selected value=%s>%s</option>"%(optionId, optionLabel)
+ else: res+="<option value=%s>%s</option>"%(optionId, optionLabel)
+ else:
+ if option==field.currentValue: res+="<option selected>%s</option>"%option
+ else: res+="<option>%s</option>"%option
+ res+='</select></td>'
+ elif field.typ=='textarea':
+ # Size is colsxrows
+ if field.size==15: size="15x15"
+ else: size=field.size
+ cols, rows=size.split('x')
+ res+='<td><textarea name="%s" rows="%s" cols="%s">%s</textarea></td>'%(field.name, rows, cols, field.currentValue)
+ elif field.typ=='submit':
+ res+='<td><input type=submit value="%s"></td>'%field.name
+ elif field.typ=='hidden':
+ if type(field.currentValue)==type([]): currentValue=field.currentValue
+ else: currentValue=[field.currentValue]
+ res=""
+ for value in currentValue:
+ res+='<input name="%s" type=hidden value="%s">'%(field.name, value)
+ return res
+ elif field.typ=='checkbox' or field.typ=='radio':
+ res+='<td>'
+ # print "##### currentValue:", field.currentValue # TBC
+ for option in field.optionList:
+ if type(option)==type(()): optionValue, optionLabel=option
+ else: optionValue, optionLabel=option, option
+ res+='<input type="%s" name="%s" value="%s"'%(field.typ, field.name, optionValue)
+ if type(field.currentValue)==type([]):
+ if optionValue in field.currentValue: res+=' checked'
+ else:
+ if optionValue==field.currentValue: res+=' checked'
+ res+='> %s<br>'%optionLabel
+ res+='</td>'
+ if field.errorMessage:
+ res+="<td><font color=red>%s</font></td>"%field.errorMessage
+ else:
+ res+="<td> </td>"
+ return res+"</tr>"
+def hiddenMask(field):
+ if type(field.currentValue)==type([]): currentValue=field.currentValue
+ else: currentValue=[field.currentValue]
+ res=""
+ for value in currentValue:
+ res+='<input name="%s" type=hidden value="%s">'%(field.name, value)
+ return res
+def defaultHeader(label):
+ return "<table>"
+def defaultFooter(label):
+ return "</table>"
+def echoMask(label):
+ return label
diff --git a/cherrypy/lib/form.py b/cherrypy/lib/form.py new file mode 100644 index 00000000..e35e1f24 --- /dev/null +++ b/cherrypy/lib/form.py @@ -0,0 +1,124 @@ +"""
+Copyright (c) 2004, CherryPy Team (team@cherrypy.org)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the CherryPy Team nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+"""
+
+"""
+Simple form handling module.
+"""
+
+from cherrypy import cpg
+import defaultformmask
+
+class FormField:
+ def __init__(self, label, name, typ, mask=None, mandatory=0, size=15, optionList=[], defaultValue='', defaultMessage='', validate=None):
+ self.isField=1
+ self.label=label
+ self.name=name
+ self.typ=typ
+ if not mask: self.mask=defaultformmask.defaultMask
+ else: self.mask=mask
+ self.mandatory=mandatory
+ self.size=size
+ self.optionList=optionList
+ self.defaultValue=defaultValue
+ self.defaultMessage=defaultMessage
+ self.validate=validate
+ self.errorMessage=""
+ def render(self, leaveValues):
+ if leaveValues:
+ if self.typ!='submit':
+ if cpg.request.paramMap.has_key(self.name): self.currentValue=cpg.request.paramMap[self.name]
+ else: self.currentValue=""
+ else: self.currentValue=self.defaultValue
+ else:
+ self.currentValue=self.defaultValue
+ self.errorMessage=self.defaultMessage
+ return self.mask(self)
+
+class FormSeparator:
+ def __init__(self, label, mask):
+ self.isField=0
+ self.label=label
+ self.mask=mask
+ def render(self, dummy):
+ return self.mask(self.label)
+
+class Form:
+ method="post"
+ enctype=""
+ def formView(self, leaveValues=0):
+ if self.enctype: enctypeTag='enctype="%s"'%self.enctype
+ else: enctypeTag=""
+ res='<form method="%s" %s action="postForm">'%(self.method, enctypeTag)
+ for field in self.fieldList:
+ res+=field.render(leaveValues)
+ return res+"</form>"
+ def validateFields(self):
+ # Should be subclassed
+ # Update field's errorMessage value to set an error
+ pass
+ def validateForm(self):
+ # Reset errorMesage for each field
+ for field in self.fieldList:
+ if field.isField: field.errorMessage=""
+
+ # Validate mandatory fields
+ for field in self.fieldList:
+ if field.isField and field.mandatory and (not cpg.request.paramMap.has_key(field.name) or not cpg.request.paramMap[field.name]): field.errorMessage="Missing"
+
+ # Validate fields one by one
+ for field in self.fieldList:
+ if field.isField and field.validate and not field.errorMessage:
+ if cpg.request.paramMap.has_key(field.name): value=cpg.request.paramMap[field.name]
+ else: value=""
+ field.errorMessage=field.validate(value)
+
+ # Validate all fields together (ie: check that passwords match)
+ self.validateFields()
+ for field in self.fieldList:
+ if field.isField and field.errorMessage: return 0
+ return 1
+ def setFieldErrorMessage(self, fieldName, errorMessage):
+ for field in self.fieldList:
+ if field.isField and field.name==fieldName: field.errorMessage=errorMessage
+ def getFieldOptionList(self, fieldName):
+ for field in self.fieldList:
+ if field.isField and field.name==fieldName: return field.optionList
+ def getFieldDefaultValue(self, fieldName):
+ for field in self.fieldList:
+ if field.isField and field.name==fieldName: return field.defaultValue
+ def setFieldDefaultValue(self, fieldName, defaultValue):
+ for field in self.fieldList:
+ if field.isField and field.name==fieldName: field.defaultValue=defaultValue
+
+ def getFieldNameList(self, exceptList=[]):
+ fieldNameList=[]
+ for field in self.fieldList:
+ if field.isField and field.name and field.name not in exceptList: fieldNameList.append(field.name)
+ return fieldNameList
+
+
@@ -22,7 +22,7 @@ setup(name="CherryPy", author_email="team@cherrypy.org", url="http://www.cherrypy.org", license="BSD", - packages=["cherrypy", "cherrypy.lib", "cherrypy.lib.filter"], + packages=["cherrypy", "cherrypy.lib", "cherrypy.lib.filter", "cherrypy.tutorial", "cherrypy.test"], download_url="http://trac.cherrypy.org/cgi-bin/trac.cgi/wiki/CherryPyDownload" ) |