Home | Trees | Indices | Help |
|
---|
|
1 from cherrypy import request 2 from turbogears import validators, expose 3 from turbogears.util import setlike, Bunch, request_available 4 from turbogears.widgets.base import Widget, CompoundWidget, WidgetsList, \ 5 CoreWD, RenderOnlyWD 6 7 __all__ = ["InputWidget", "CompoundInputWidget", "RepeatingInputWidget", 8 "FormField", "FormFieldsContainer", "CompoundFormField", 9 "RepeatingFormField", "Label", "TextField", "PasswordField", 10 "HiddenField", "FileField", "Button", "SubmitButton", 11 "ResetButton", "ImageButton", "CheckBox", "TextArea", 12 "SelectionField", "SingleSelectField", "MultipleSelectField", 13 "RadioButtonList", "CheckBoxList", "FieldSet", 14 "RepeatingFieldSet", "Form", "TableForm", "ListForm", 15 "WidgetsList"]16 17 18 ############################################################################# 19 # Functions and classes to manage input widgets # 20 ############################################################################# 21 22 -def append_to_path(widget, repetition):23 path = [] 24 if request_available(): 25 if hasattr(request, "tg_widgets_path"): 26 path = request.tg_widgets_path 27 else: 28 request.tg_widgets_path = path 29 if not path or path[-1].widget is not widget: 30 path.append(Bunch(widget=widget, 31 repetition=repetition)) 32 return True 33 else: 34 return False35 3941 default_path = [Bunch(widget=default_widget, 42 repetition=default_repetition)] 43 return getattr(request, "tg_widgets_path", default_path)4446 def _update_path(self, *args, **kw): 47 update = append_to_path(self, None) 48 returnval = func(self, *args, **kw) 49 if update: 50 pop_from_path() 51 return returnval52 return _update_path 53 5658 path = [] 59 if isinstance(item, basestring): 60 path = item.split('.') 61 index = 0 62 for key in path: 63 if '-' in key: 64 key, num = key.split('-') 65 path[index] = key, int(num) 66 else: 67 path[index] = key, None 68 index += 1 69 elif hasattr(item, "name"): 70 path = [(item.name, None)] 71 if base_path: 72 if not isinstance(base_path[0], tuple): 73 base_path = adapt_path(base_path) 74 path = base_path + path 75 return path7678 if not path: 79 return None 80 else: 81 if not isinstance(path[0], tuple): 82 path = adapt_path(path) 83 returnval = value 84 for name, index in path: 85 if isinstance(returnval, dict): 86 returnval = returnval.get(name) 87 if index is not None: 88 if isinstance(returnval, list): 89 try: 90 returnval = returnval[index] 91 except IndexError: 92 returnval = None 93 else: 94 returnval = None 95 return returnval9698 if not path: 99 return None 100 else: 101 if not isinstance(path[0], tuple): 102 path = adapt_path(path) 103 for name, index in path: 104 params_to_parse = params.copy() 105 params = {} 106 for k,v in params_to_parse.iteritems(): 107 if isinstance(v, dict): 108 if name in v: 109 params[k] = v[name] 110 if index is not None: 111 if isinstance(params[k], list): 112 try: 113 params[k] = params[k][index] 114 except IndexError: 115 params[k] = None 116 else: 117 params[k] = None 118 return params119121 name = [] 122 for item in path: 123 if item.repetition is not None: 124 name.append(item.widget.name + repeating_marker + str(item.repetition)) 125 else: 126 name.append(item.widget.name) 127 return nesting_marker.join(name)128129 130 ############################################################################### 131 # Base class for a widget that can generate input for the app. 132 ############################################################################### 133 134 -class InputWidget(Widget):135 validator = None 136 params = ["convert"] 137 params_doc = {'convert': 'Should the value be coerced by the validator at ' 138 'display?'} 139 convert = True 140250142 """Initialize an input widget. 143 144 It accepts the following parameters (besides those listed at params): 145 146 name: 147 Name of the input element. Will be the name of the variable 148 the widget's input will be available at when submitted. 149 150 validator: 151 Formencode validator that will validate and coerce the input 152 this widget generates. 153 154 """ 155 if name is not None and ('-' in name or '.' in name): 156 raise ValueError, ("The name of an InputWidget must not contain " 157 "the '-' or '.' characters") 158 159 super(InputWidget, self).__init__(name, **params) 160 161 if validator: 162 self.validator = validator163 164 @property 165 @update_path 168 169 @property171 if self.path and getattr(self.path[0].widget, "form", False): 172 return self.path[1:] 173 else: 174 return self.path175 176 @property178 if self.path: 179 validated_form = getattr(request, "validated_form", None) 180 return self.path[0].widget is validated_form 181 else: 182 return False183185 root_widget = self.path[0].widget 186 if root_widget is self: 187 return self.validator 188 else: 189 if getattr(root_widget, "form", False): 190 name_path = self.name_path 191 else: 192 name_path = self.name_path[1:] 193 validator = root_widget.validator 194 for name in [i.widget.name for i in name_path]: 195 if hasattr(validator, "fields"): 196 validator = validator.fields.get(name) 197 elif hasattr(validator, "validators"): 198 for v in validator.validators: 199 if hasattr(v, "fields") and (name in v.fields): 200 validator = v.fields[name] 201 break 202 else: 203 break 204 return validator205207 if hasattr(request, "input_values") and self.is_validated: 208 input_submitted = True 209 iv = retrieve_value_by_path(request.input_values, self.name_path) 210 else: 211 input_submitted = False 212 iv = None 213 # there are some input fields that when nothing is checked/selected 214 # instead of sending a nice name="" are totally missing from 215 # input_values, this little workaround let's us manage them nicely 216 # without interfering with other types of fields, we need this to 217 # keep track of their empty status otherwise if the form is going to be 218 # redisplayed for some errors they end up to use their defaults values 219 # instead of being empty since FE doesn't validate a failing Schema. 220 # posterity note: this is also why we need if_missing=None in 221 # validators.Schema, see ticket #696. 222 no_input_if_empty = getattr(self, "no_input_if_empty", False) 223 if iv is not None or (input_submitted and no_input_if_empty): 224 value = iv 225 else: 226 if self.validator and params["convert"] and not input_submitted: 227 value = self.validator.from_python(value) 228 return value229 230 @update_path 233 234 @property 235 @update_path237 return build_name_from_path(self.name_path)238 239 @property 240 @update_path242 errors = getattr(request, "validation_errors", {}) 243 return retrieve_value_by_path(errors, self.name_path)244246 super(InputWidget, self).update_params(d) 247 d["name"] = build_name_from_path(self.name_path) 248 errors = getattr(request, "validation_errors", {}) 249 d["error"] = retrieve_value_by_path(errors, self.name_path)253322 343255 super(CompoundInputWidget, self).update_params(params) 256 params['error_for'] = lambda f: self.error_for(f, True)257259 """Return the value for a child widget. 260 261 ``item`` is the child widget instance or it's name, ``value`` is a 262 dict containing the value for this compound widget. 263 264 """ 265 path = path_from_item(item) 266 return retrieve_value_by_path(value, path)267269 """Return the parameters for a child widget. 270 271 ``item`` is the child widget instance or it's name, ``params`` is a 272 dict containing the parameters passed to this compound widget. 273 274 """ 275 path = path_from_item(item) 276 return retrieve_params_by_path(params, path)277279 """Return the Invalid exception associated with a child widget. 280 281 The exception is stored in the request local storage. ``item`` is the 282 child widget instance or it's name. 283 284 """ 285 if self.is_validated: 286 path = path_from_item(item, self.name_path) 287 errors = getattr(request, "validation_errors", {}) 288 returnval = retrieve_value_by_path(errors, path) 289 if suppress_errors and \ 290 isinstance(returnval, dict) or isinstance(returnval, list): 291 return None 292 else: 293 return returnval 294 else: 295 return None296298 """Convert value into a dict suitable for propagating values to child 299 widgets. 300 301 If value is a dict it will pass through, if it's another kind of 302 object, attributes which match child widgets' names will tried to be 303 fetched. 304 305 """ 306 if isinstance(value, dict): 307 return value 308 else: 309 value_as_dict = {} 310 for w in self.iter_member_widgets(): 311 try: 312 value_as_dict[w.name] = getattr(value, w.name) 313 except AttributeError: 314 pass 315 return value_as_dict316318 """Adjust a value for displaying in a widget.""" 319 if value is not None: 320 value = self.dictify_value(value) 321 return super(CompoundWidget, self).adjust_value(value, **params)346 """Base class for a compound widget which can be repeated.""" 347 348 repeating = True 349 params = ["repetitions"] 350 params_doc = {'repetitions': 'Number of repetitions that should be ' 351 'rendered'} 352 repetitions = 1 353413355 path_reference = self.path[-1] 356 repetition = path_reference.repetition 357 if repetition is not None: 358 path_reference.repetition = None 359 super(RepeatingInputWidget, self).update_params(d) 360 if repetition is None: 361 repetitions = d.pop("repetitions") 362 if isinstance(repetitions, int): 363 repetitions = range(repetitions) 364 else: 365 repetitions = [repetition] 366 d["repetitions"] = RepeatingRange(repetitions, path_reference)367369 """Return the value for a child widget. 370 371 ``item`` is the child widget instance or it's name, ``value`` is a dict 372 containing the value for this compound widget. 373 374 """ 375 if isinstance(value, list): 376 try: 377 value = value[self.path[-1].repetition] 378 except IndexError: 379 value = None 380 else: 381 value = None 382 path = path_from_item(item) 383 return retrieve_value_by_path(value, path)384386 """Return the parameters for a child widget. 387 388 ``item`` is the child widget instance or it's name, ``params`` is a 389 dict containing the parameters passed to this compound widget. 390 391 """ 392 item_params = {} 393 for k,v in params.iteritems(): 394 if isinstance(v, list) and k is not "repetitions": 395 try: 396 item_params[k] = v[self.path[-1].repetition] 397 except IndexError: 398 pass 399 path = path_from_item(item) 400 return retrieve_params_by_path(item_params, path)401403 """Convert list of values into a list of dicts suitable for propagating 404 values to child widgets. 405 406 If value is a list of dicts it will pass through, if it's another kind 407 of object, attributes which match child widgets' names will tried to be 408 fetched. 409 410 """ 411 return [super(RepeatingInputWidget, self).dictify_value(v) 412 for v in value]414 415 ############################################################################# 416 # Base classes # 417 ############################################################################# 418 419 -class FormField(InputWidget):420 """An input widget that can be included inside a Form or Fieldset. 421 422 It accepts the following parameters (besides those listed at params): 423 424 label 425 The label text that the container form/fieldset will generate for the 426 widget. If empty, the capitalized name will be used. 427 help_text 428 The help text that the container form/fieldset will generate for the 429 widget. 430 431 """ 432 _name = "widget" 433 label = None 434 help_text = None 435 params = ["field_class", "css_classes"] 436 params_doc = {'field_class' : 'CSS class for the field', 437 'css_classes' : 'List of extra CSS classes for the field'} 438 field_class = None 439 css_classes = [] 440489442 return self._name443 448 name = property(_get_name, _set_name) 449 450 @property452 validator = self._retrieve_validator_from_validation_schema() 453 if validator is None: 454 return False 455 else: 456 try: 457 validator.to_python('') 458 except validators.Invalid: 459 return True 460 else: 461 return False462 463 @property465 return build_name_from_path(self.path, '_', '_')466468 super(FormField, self).__init__(name, **kw) 469 if label is not None: 470 self.label = label 471 472 if help_text is not None: 473 self.help_text = help_text 474 475 if self.field_class is None: 476 self.field_class = self.__class__.__name__.lower()477479 super(FormField, self).update_params(d) 480 if self.is_required: 481 d["field_class"] = " ".join([d["field_class"], "requiredfield"]) 482 if d.get('error', None): 483 d["field_class"] = " ".join([d["field_class"], "erroneousfield"]) 484 if d["css_classes"]: 485 d["field_class"] = " ".join([d["field_class"]] + d["css_classes"]) 486 d["label"] = self.label 487 d["help_text"] = self.help_text 488 d["field_id"] = self.field_id490 491 # A decorator that provides field_for functionality to the 492 # decorated FormFieldsContainer's method 493 -def retrieve_field_for(func):494 @update_path 495 def retrieve_field_for(self=None, item=None, *args, **kw): 496 path = path_from_item(item) 497 field = self 498 for name, index in path: 499 if field is not None: 500 field = field.get_field_by_name(name) 501 append_to_path(field, index) 502 if field is not None: 503 returnval = func(self, field, *args, **kw) 504 else: 505 returnval = "Field for '%s' not found." % item 506 for i in range(len(path)): 507 pop_from_path() 508 return returnval509 return retrieve_field_for 510513 """A container for FormFields. 514 515 Has two member_widgets lists: 516 - fields 517 - hidden_fields 518 519 It provides the template with 3 useful functions: 520 - field_for(name) 521 Returns the child named ``name``. 522 - value_for(name) 523 Returns the value for the child named ``name`` (name can also be 524 a widget instance so fields can be iterated). 525 - params_for(name) 526 Returns the display-time parameters for the child named ``name`` 527 (can also be a widget instance so fields can be iterated). 528 - display_field_for(name) 529 Displays the child named ``name`` automatically propagating value 530 an params. ``name`` can also be a widget instance. 531 - error_for(name) 532 Returns the validation error the child named ``name`` generated. 533 Again, ``name`` can also be a widget instance. 534 535 """ 536 member_widgets = ["fields", "hidden_fields"] 537 fields = [] 538 hidden_fields = [] 539 params = ["disabled_fields"] 540 disabled_fields = set() 541 542 @property596544 for widget in self.iter_member_widgets(): 545 if getattr(widget, "file_upload", False): 546 return True 547 return False548550 for widget in self.iter_member_widgets(): 551 if widget.name == name: 552 return widget 553 return default554 555 @retrieve_field_for 558 559 @retrieve_field_for 562564 """Return the member widget named item. 565 566 This function should *only* be used inside a FormFieldsContainer 567 template, really, else the path acrobatics will lead to unexpected 568 results. 569 570 """ 571 field = self.get_field_by_name(item, None) 572 if field is None: 573 raise ValueError("Field for '%s' not found." % item) 574 return field575577 super(FormFieldsContainer, self).update_params(d) 578 d["display_field_for"] = lambda f: self.display_field_for(f, 579 d["value_for"](f), **d["params_for"](f)) 580 d["render_field_for"] = lambda f: self.display_field_for(f, 581 d["value_for"](f), **d["params_for"](f)) 582 d["field_for"] = self._field_for 583 visible_fields = [] 584 hidden_fields = [] 585 #XXX: Ugly hack, this badly needs a better fix. Note to meself: 586 # CompoundFormField has no fields or hidden_fields member_widgets, 587 # related to [1736]'s refactoring. 588 for field in d.get("fields", []) + d.get("hidden_fields", []): 589 if field.name not in d["disabled_fields"]: 590 if getattr(field, "hidden", False): 591 hidden_fields.append(field) 592 else: 593 visible_fields.append(field) 594 d["fields"] = visible_fields 595 d["hidden_fields"] = hidden_fields599 is_required = False600 604605 606 ############################################################################# 607 # Fields # 608 ############################################################################# 609 610 -class Label(FormField):611 """A simple label for a form field.""" 612 613 template = """ 614 <label xmlns:py="http://purl.org/kid/ns#" 615 id="${field_id}" 616 class="${field_class}" 617 py:content="value" 618 py:attrs="attrs" 619 /> 620 """ 621 params = ["attrs"] 622 params_doc = {'attrs' : 'Dictionary containing extra (X)HTML attributes for' 623 'the label tag'} 624 attrs = {}625 629632 """A standard, single-line text field.""" 633 634 template = """ 635 <input xmlns:py="http://purl.org/kid/ns#" 636 type="text" 637 name="${name}" 638 class="${field_class}" 639 id="${field_id}" 640 value="${value}" 641 py:attrs="attrs" 642 /> 643 """ 644 params = ["attrs"] 645 params_doc = {'attrs' : 'Dictionary containing extra (X)HTML attributes for' 646 ' the input tag'} 647 attrs = {}648651 name = "Text Field" 652 for_widget = TextField("your_name", 653 default="Your Name Here", 654 attrs=dict(size="30"))655658 """A password field which masks letters with * characters.""" 659 660 template = """ 661 <input xmlns:py="http://purl.org/kid/ns#" 662 type="password" 663 name="${name}" 664 class="${field_class}" 665 id="${field_id}" 666 value="${value}" 667 py:attrs="attrs" 668 /> 669 """ 670 params = ["attrs"] 671 params_doc = {'attrs' : 'Dictionary containing extra (X)HTML attributes for' 672 'the password input tag'} 673 attrs = {}674677 name = "Password Field" 678 for_widget = PasswordField("your_secret", 679 default="Top Secret Password")680683 template = """ 684 <input xmlns:py="http://purl.org/kid/ns#" 685 type="hidden" 686 name="${name}" 687 class="${field_class}" 688 id="${field_id}" 689 value="${value}" 690 py:attrs="attrs" 691 /> 692 """ 693 params = ["attrs"] 694 params_doc = {'attrs' : 'Dictionary containing extra (X)HTML attributes for' 695 ' the hidden input tag'} 696 attrs = {} 697 hidden = True698 703706 template = """ 707 <input xmlns:py="http://purl.org/kid/ns#" 708 type="file" 709 name="${name}" 710 class="${field_class}" 711 id="${field_id}" 712 py:attrs="attrs" 713 /> 714 """ 715 params = ["attrs"] 716 params_doc = {'attrs' : 'Dictionary containing extra (X)HTML attributes for' 717 ' the file input tag'} 718 attrs = {} 719 file_upload = True 720723 728731 template = """ 732 <input xmlns:py="http://purl.org/kid/ns#" 733 type="button" 734 class="${field_class}" 735 value="${value}" 736 py:attrs="attrs" 737 /> 738 """ 739 params = ["attrs"] 740 params_doc = {'attrs' : 'Dictionary containing extra (X)HTML attributes for' 741 ' the button input tag'} 742 attrs = {} 743749 754745 super(Button, self).update_params(d) 746 if self.is_named: 747 d['attrs']['name'] = d["name"] 748 d['attrs']['id'] = d["field_id"]757 template = """ 758 <input xmlns:py="http://purl.org/kid/ns#" 759 type="submit" 760 class="${field_class}" 761 value="${value}" 762 py:attrs="attrs" 763 /> 764 """765 770773 template = """ 774 <input xmlns:py="http://purl.org/kid/ns#" 775 type="reset" 776 class="${field_class}" 777 value="${value}" 778 py:attrs="attrs" 779 /> 780 """781 786789 template = """ 790 <input xmlns:py="http://purl.org/kid/ns#" 791 type="image" 792 src="${src}" 793 width="${width}" 794 height="${height}" 795 alt="${alt}" 796 class="${field_class}" 797 value="${value}" 798 py:attrs="attrs" 799 /> 800 """ 801 params = ["src", "width", "height", "alt"] 802 params_doc = {'src' : 'Source of the image', 803 'width' : 'Width of the image', 804 'height' : 'Height of the image', 805 'alt': 'Alternate text for the image'} 806 src = None 807 width = None 808 height = None 809 alt = None810813 name = "Image Button" 814 for_widget = ImageButton("your_image_button", src="/tg_static/images/toolbox_logo.png")815818 template = """ 819 <input xmlns:py="http://purl.org/kid/ns#" 820 type="checkbox" 821 name="${name}" 822 class="${field_class}" 823 id="${field_id}" 824 py:attrs="attrs" 825 /> 826 """ 827 # an unchecked checkbox doesn't submit anything 828 no_input_if_empty = True 829 params = ["attrs"] 830 params_doc = {'attrs' : 'Dictionary containing extra (X)HTML attributes for' 831 ' the checkbox input tag'} 832 attrs = {} 833847835 super(CheckBox, self).__init__(*args, **kw) 836 if not self.validator: 837 self.validator = validators.Bool()838840 super(CheckBox, self).update_params(d) 841 try: 842 value = self.validator.to_python(d['value']) 843 except validators.Invalid: 844 value = False 845 if value: 846 d['attrs']['checked'] = 'checked'850 for_widget = CheckBox(name="your_checkbox", 851 default=True, 852 help_text="Just click me...") 853 template = """ 854 <div xmlns:py="http://purl.org/kid/ns#"> 855 ${for_widget.display()} 856 <label for="${for_widget.field_id}" 857 py:content="for_widget.help_text" 858 /> 859 </div> 860 """861864 template = """ 865 <textarea xmlns:py="http://purl.org/kid/ns#" 866 name="${name}" 867 class="${field_class}" 868 id="${field_id}" 869 rows="${rows}" 870 cols="${cols}" 871 py:attrs="attrs" 872 py:content="value" 873 /> 874 """ 875 params = ["rows", "cols", "attrs"] 876 params_doc = {'attrs' : 'Dictionary containing extra (X)HTML attributes for' 877 ' the textarea tag', 878 'rows' : 'Number of rows to render', 879 'cols' : 'Number of columns to render'} 880 rows = 7 881 cols = 50 882 attrs = {}883886 name = "Text Area" 887 for_widget = TextArea(name="your_textarea", 888 default="Your Comment Here", 889 rows=5, cols=40)890893 # an empty selection doesn't submit anything 894 no_input_if_empty = True 895 _multiple_selection = False 896 _selected_verb = None 897 params = ["options"] 898 params_doc = {'options' : 'A list of tuples with the options for the select' 899 'field'} 900 options = [] 901 convert = False 9021027904 super(SelectionField, self).__init__(*args, **kw) 905 if not self.validator: 906 try: 907 self.validator = self._guess_validator() 908 except Exception, err: 909 raise ValueError( 910 "No validator specified and couldn't guess one:\n%s\n" 911 "Please explicitly specify a validator for the %s." 912 % (err, self.__class__.__name__)) 913 # Only override the user-provided validator if it's not a ForEach one, 914 # which usually means the user needs to perform validation on the list 915 # as a whole. 916 if (self._multiple_selection and 917 not isinstance(self.validator, validators.ForEach)): 918 self.validator = validators.MultipleSelection(self.validator)919921 """Inspect sample option value to guess validator (crude).""" 922 sample_option = self._get_sample_option() 923 if isinstance(sample_option, int): 924 return validators.Int() 925 elif isinstance(sample_option, basestring): 926 return validators.String() 927 else: 928 raise TypeError("Unknown option type in SelectionField: %r" 929 % (sample_option,))930932 options = self._extend_options(self.options) 933 if options: 934 if isinstance(options[0][1], list): 935 sample = options[0][1][0] 936 else: 937 sample = options[0] 938 return sample[0] 939 else: 940 return None941943 if (len(opts) > 0) and not isinstance(opts[0], (tuple,list)): 944 new_opts = [] 945 for opt in opts: 946 new_opts.append((opt,opt)) 947 return new_opts 948 return opts949951 super(SelectionField, self).update_params(d) 952 grouped_options = [] 953 options = [] 954 d['options'] = self._extend_options(d['options']) 955 for optgroup in d["options"]: 956 if isinstance(optgroup[1], list): 957 group = True 958 optlist = optgroup[1][:] 959 else: 960 group = False 961 optlist = [optgroup] 962 for i, option in enumerate(optlist): 963 option_value = option[0] 964 option_attrs = len(option) > 2 and dict(option[2]) or {} 965 if self._is_option_selected(option_value, d['value']): 966 option_attrs[self._selected_verb] = self._selected_verb 967 option_value = self.validator.from_python(option_value) 968 if self._multiple_selection: 969 if option_value: 970 option_value = option_value[0] 971 else: 972 option_value = None 973 if option_value is None: 974 option_value = '' 975 optlist[i] = (option_value, option[1], option_attrs) 976 options.extend(optlist) 977 if group: 978 grouped_options.append((optgroup[0], optlist)) 979 # options provides a list of *flat* options leaving out any eventual 980 # group, useful for backward compatibility and simpler widgets 981 d["options"] = options 982 if grouped_options: 983 d["grouped_options"] = grouped_options 984 else: 985 d["grouped_options"] = [(None, options)]986988 if self._multiple_selection: 989 if isinstance(value, basestring): 990 # single unconverted value 991 try: 992 value = self.validator.to_python(value) 993 except validators.Invalid: 994 return False 995 if not value: 996 return False 997 else: 998 if not value: 999 return False 1000 # multiple values - check whether list or set may 1001 # need conversion by looking at its first item 1002 for v in value: 1003 if isinstance(v, basestring): 1004 try: 1005 value = self.validator.to_python(value) 1006 except validators.Invalid: 1007 return False 1008 if not value: 1009 return False 1010 break 1011 if option_value is None: 1012 for v in value: 1013 if v is None: 1014 return True 1015 return False 1016 return option_value in value 1017 else: 1018 if isinstance(value, basestring): 1019 # value may need conversion 1020 try: 1021 value = self.validator.to_python(value) 1022 except validators.Invalid: 1023 return False 1024 if option_value is None: 1025 return value is None 1026 return option_value == value1030 template = """ 1031 <select xmlns:py="http://purl.org/kid/ns#" 1032 name="${name}" 1033 class="${field_class}" 1034 id="${field_id}" 1035 py:attrs="attrs" 1036 > 1037 <optgroup py:for="group, options in grouped_options" 1038 label="${group}" 1039 py:strip="not group" 1040 > 1041 <option py:for="value, desc, attrs in options" 1042 value="${value}" 1043 py:attrs="attrs" 1044 py:content="desc" 1045 /> 1046 </optgroup> 1047 </select> 1048 """ 1049 _selected_verb = 'selected' 1050 params = ["attrs"] 1051 params_doc = {'attrs' : 'Dictionary containing extra (X)HTML attributes for' 1052 ' the select tag'} 1053 attrs = {}10541057 name = "Single Select Field" 1058 for_widget = SingleSelectField("your_single_select_field", 1059 options=[(1, "Python"), 1060 (2, "Java"), 1061 (3, "Pascal"), 1062 (4, "Ruby")], 1063 default=2)10641067 template = """ 1068 <select xmlns:py="http://purl.org/kid/ns#" 1069 multiple="multiple" 1070 size="${size}" 1071 name="${name}" 1072 class="${field_class}" 1073 id="${field_id}" 1074 py:attrs="attrs" 1075 > 1076 <optgroup py:for="group, options in grouped_options" 1077 label="${group}" 1078 py:strip="not group" 1079 > 1080 <option py:for="value, desc, attrs in options" 1081 value="${value}" 1082 py:attrs="attrs" 1083 py:content="desc" 1084 /> 1085 </optgroup> 1086 </select> 1087 """ 1088 _multiple_selection = True 1089 _selected_verb = 'selected' 1090 params = ["size", "attrs"] 1091 params_doc = {'size' : 'Number of options to show without scrolling'} 1092 attrs = {} 1093 size = 510941097 name = "Multiple Select Field" 1098 for_widget = MultipleSelectField("your_multiple_select_field", 1099 options=[("a", "Python"), 1100 ("b", "Java"), 1101 ("c", "Pascal"), 1102 ("d", "Ruby")], 1103 default=["a","c","d"])11041107 template = """ 1108 <ul xmlns:py="http://purl.org/kid/ns#" 1109 class="${field_class}" 1110 id="${field_id}" 1111 py:attrs="list_attrs" 1112 > 1113 <li py:for="value, desc, attrs in options"> 1114 <input type="radio" 1115 name="${name}" 1116 id="${field_id}_${value}" 1117 value="${value}" 1118 py:attrs="attrs" 1119 /> 1120 <label for="${field_id}_${value}" py:content="desc" /> 1121 </li> 1122 </ul> 1123 """ 1124 _selected_verb = 'checked' 1125 params = ["list_attrs"] 1126 params_doc = {'list_attrs' : 'Extra (X)HTML attributes for the ul tag'} 1127 list_attrs = {}11281131 name = "RadioButton List" 1132 for_widget = RadioButtonList("your_radiobutton_list", 1133 options=list(enumerate("Python Java Pascal Ruby".split())), default=3)11341137 template = """ 1138 <ul xmlns:py="http://purl.org/kid/ns#" 1139 class="${field_class}" 1140 id="${field_id}" 1141 py:attrs="list_attrs" 1142 > 1143 <li py:for="value, desc, attrs in options"> 1144 <input type="checkbox" 1145 name="${name}" 1146 id="${field_id}_${value}" 1147 value="${value}" 1148 py:attrs="attrs" 1149 /> 1150 <label for="${field_id}_${value}" py:content="desc" /> 1151 </li> 1152 </ul> 1153 """ 1154 _multiple_selection = True 1155 _selected_verb = 'checked' 1156 params = ["list_attrs"] 1157 params_doc = {'list_attrs' : 'Extra (X)HTML attributes for the ul tag'} 1158 list_attrs = {}11591162 name = "CheckBox List" 1163 for_widget = CheckBoxList("your_checkbox_list", 1164 options=list(enumerate("Python Java Pascal Ruby".split())), 1165 default=[0,3])11661169 template=""" 1170 <fieldset xmlns:py="http://purl.org/kid/ns#" 1171 class="${field_class}" 1172 id="${field_id}" 1173 > 1174 <legend py:if="legend" py:content="legend" /> 1175 <div py:for="field in hidden_fields" 1176 py:replace="field.display(value_for(field), **params_for(field))" 1177 /> 1178 <div py:for="field in fields"> 1179 <label class="fieldlabel" for="${field.field_id}" py:content="field.label" /> 1180 <span py:replace="field.display(value_for(field), **params_for(field))" /> 1181 <span py:if="error_for(field)" class="fielderror" py:content="error_for(field)" /> 1182 <span py:if="field.help_text" class="fieldhelp" py:content="field.help_text" /> 1183 </div> 1184 </fieldset> 1185 """ 1186 params = ["legend"] 1187 params_doc = {'legend' : 'Text to display as the legend for the fieldset'} 1188 legend = None11891192 name = "FieldSet" 1193 for_widget = FieldSet("your_fieldset", 1194 legend="Range", 1195 fields=[TextField(name="lower_limit", 1196 label="Lower Limit"), 1197 TextField(name="upper_limit", 1198 label="Upper Limit")])11991202 template=""" 1203 <div xmlns:py="http://purl.org/kid/ns#"> 1204 <fieldset py:for="repetition in repetitions" 1205 class="${field_class}" 1206 id="${field_id}_${repetition}" 1207 > 1208 <legend py:if="legend" py:content="legend" /> 1209 <div py:for="field in hidden_fields" 1210 py:replace="field.display(value_for(field), **params_for(field))" 1211 /> 1212 <div py:for="field in fields"> 1213 <label class="fieldlabel" for="${field.field_id}" py:content="field.label" /> 1214 <span py:replace="field.display(value_for(field), **params_for(field))" /> 1215 <span py:if="error_for(field)" class="fielderror" py:content="error_for(field)" /> 1216 <span py:if="field.help_text" class="fieldhelp" py:content="field.help_text" /> 1217 </div> 1218 </fieldset> 1219 </div> 1220 """ 1221 params = ["legend"] 1222 params_doc = {'legend' : 'Text to display as the legend for the fieldset'} 1223 legend = None12241227 name = "Repeating FieldSet" 1228 for_widget = RepeatingFieldSet("your_repeating_fieldset", 1229 legend='Range', 1230 repetitions=3, 1231 fields=[TextField(name="lower_limit", 1232 label="Lower Limit"), 1233 TextField(name="upper_limit", 1234 label="Upper Limit")])12351236 1237 ############################################################################# 1238 # Forms # 1239 ############################################################################# 1240 1241 -class Form(FormFieldsContainer):1242 form = True 1243 name = "form" 1244 member_widgets = ["submit"] 1245 params = ["action", "method", "form_attrs", "use_name", "submit_text"] 1246 params_doc = {'action': 'Url to POST/GET the form data', 1247 'method': 'HTTP request method', 1248 'form_attrs': 'Extra (X)HTML attributes for the form tag', 1249 'use_name': 'Whether to use the name instead of the id attribute', 1250 'submit_text': 'Text for the submit button', 1251 'disabled_fields': 'List of names of the fields we want to disable'} 1252 submit = SubmitButton() 1253 action = '' 1254 method = 'post' 1255 form_attrs = {} 1256 use_name = False # because this is deprecated in HTML and invalid in XHTML 1257 submit_text = None 125812731260 name = d.get('name') 1261 super(Form, self).update_params(d) 1262 d['name'] = name or self.name 1263 if self.file_upload: 1264 d['form_attrs']['enctype'] = 'multipart/form-data'1265 1269 1270 @property1276 """Form with simple table layout.""" 1277 1278 # note that even hidden fields must live inside a block element 1279 template = """ 1280 <form xmlns:py="http://purl.org/kid/ns#" 1281 name="${use_name and name or None}" 1282 id="${not use_name and name or None}" 1283 action="${action}" 1284 method="${method}" 1285 class="tableform" 1286 py:attrs="form_attrs" 1287 > 1288 <div py:if="hidden_fields" style="display:none"> 1289 <div py:for="field in hidden_fields" 1290 py:replace="field.display(value_for(field), **params_for(field))" 1291 /> 1292 </div> 1293 <table border="0" cellspacing="0" cellpadding="2" py:attrs="table_attrs"> 1294 <tr py:for="i, field in enumerate(fields)" class="${i % 2 and 'odd' or 'even'}"> 1295 <th> 1296 <label class="fieldlabel" for="${field.field_id}" py:content="field.label" /> 1297 </th> 1298 <td> 1299 <span py:replace="field.display(value_for(field), **params_for(field))" /> 1300 <span py:if="error_for(field)" class="fielderror" py:content="error_for(field)" /> 1301 <span py:if="field.help_text" class="fieldhelp" py:content="field.help_text" /> 1302 </td> 1303 </tr> 1304 <tr> 1305 <td> </td> 1306 <td py:content="submit.display(submit_text)" /> 1307 </tr> 1308 </table> 1309 </form> 1310 """ 1311 params = ["table_attrs"] 1312 params_doc = {'table_attrs' : 'Extra (X)HTML attributes for the Table tag'} 1313 table_attrs = {}13141317 name = "Table Form" 1318 full_class_name = "turbogears.widgets.TableForm" 1319 field1 = TextField("name") 1320 field2 = TextField("address") 1321 field3 = TextField("occupation") 1322 field4 = PasswordField("password") 1323 field5 = PasswordField("reserved") # will never show 1324 field6 = HiddenField("hidden_info") 1325 for_widget = TableForm("TableForm", 1326 fields=[field1, field2, field3, field4, field5, field6], 1327 action="%s/save" % full_class_name, 1328 submit_text="Submit Me") 1329 template = """ 1330 <div> 1331 ${for_widget.display(disabled_fields=["reserved"])} 1332 </div> 1333 """ 1334 1335 @expose()13381341 """Form with simple list layout.""" 1342 1343 # note that even hidden fields must live inside a block element 1344 template = """ 1345 <form xmlns:py="http://purl.org/kid/ns#" 1346 name="${use_name and name or None}" 1347 id="${not use_name and name or None}" 1348 action="${action}" 1349 method="${method}" 1350 class="listform" 1351 py:attrs="form_attrs" 1352 > 1353 <div py:if="hidden_fields" style="display:none"> 1354 <div py:for="field in hidden_fields" 1355 py:replace="field.display(value_for(field), **params_for(field))" 1356 /> 1357 </div> 1358 <ul py:attrs="list_attrs"> 1359 <li py:for="i, field in enumerate(fields)" class="${i % 2 and 'odd' or 'even'}"> 1360 <label class="fieldlabel" for="${field.field_id}" py:content="field.label" /> 1361 <span py:replace="field.display(value_for(field), **params_for(field))" /> 1362 <span py:if="error_for(field)" class="fielderror" py:content="error_for(field)" /> 1363 <span py:if="field.help_text" class="fieldhelp" py:content="field.help_text" /> 1364 </li> 1365 <li py:content="submit.display(submit_text)" /> 1366 </ul> 1367 </form> 1368 """ 1369 params = ["list_attrs"] 1370 params_doc = {'list_attrs' : 'Extra (X)HTML attributes for the ul tag'} 1371 list_attrs = {}13721375 name = "List Form" 1376 full_class_name = "turbogears.widgets.ListForm" 1377 field1 = TextField("name") 1378 field2 = TextField("address") 1379 field3 = TextField("occupation") 1380 field4 = PasswordField("password") 1381 field5 = PasswordField("reserved") # will never show 1382 field6 = HiddenField("hidden_info") 1383 for_widget = ListForm("ListForm", 1384 fields=[field1, field2, field3, field4, field5, field6], 1385 action="%s/save" % full_class_name, 1386 submit_text="Submit Me") 1387 template = """ 1388 <div> 1389 ${for_widget.display(disabled_fields=["reserved"])} 1390 </div> 1391 """ 1392 1393 @expose()1396
Home | Trees | Indices | Help |
|
---|
Generated by Epydoc 3.0.1 on Fri Jul 19 17:17:58 2019 | http://epydoc.sourceforge.net |