AJAX form submission (inline success) AJAX form submission (redirect on success) Accordion Autocomplete Input Widget Autocomplete Input Widget (with Remote Data Source) Checkbox Choice Widget Checkbox Choice Widget (inline) Checkbox Choice Widget (read-only) Checkbox Choice Widget (with required field) Checkbox Widget Checkbox Widget (read-only) Checkbox Widget (with Label) Checked Input Widget Checked Input Widget (read-only) Checked Input Widget (with Input Mask) Checked Password Widget Checked Password Widget (read-only) Checked Password Widget (redisplay on validation failure) Custom classes on outermost html element of Widgets Date Input Widget Date Parts Widget Date Parts Widget (read-only) DateTime Input Widget DateTime Input Widget (read-only) Deferred Schema Bindings Dont Validate Readonly Fields Dynamic fields: add and remove Edit Form Field Defaults File Upload Widget File Upload Widget (read-only) Hidden Widget Hidden Widget (missing, representing an Integer) Inter-Field Validation Internationalization Mapping Widget Money Input Multiple Error Messages For a Single Widget (Mapping) Multiple Error Messages For a Single Widget (Sequence) Multiple Forms on the Same Page Non-Required Fields Non-Required Number Fields Password Widget Password Widget (redisplay on validation failure) Popup and retail rendering Pyramid CSRF Demo (using schema binding) Radio Choice Widget Radio Choice Widget (inline) Radio Choice Widget (read-only) Radio Choice Widget (with int values) Read-Only Fields Require One Field or Another Rich Text Widget (TinyMCE) Rich Text Widget (delayed) Rich Text Widget (internationalized) Rich Text Widget (read-only) Select Widget Select Widget (read-only) Select Widget (with Integer values) Select Widget (with default) Select Widget (with deferred choices and default) Select Widget (with multiple default integers) Select Widget (with multiple) Select Widget (with optgroup and label attributes) Select Widget (with optgroup) Select Widget (with size) Select Widget (with unicode) Select2 Widget Select2 Widget (with multiple) Select2 Widget (with optgroup) Sequence (of Mappings) with Ordering Enabled Sequence With Prototype that Has No Name Sequence of Autocomplete Widgets Sequence of Constrained Min and Max Lengths Sequence of Date Inputs Sequence of Defaulted Selects Sequence of Defaulted Selects (with Initial Item) Sequence of File Upload Widgets Sequence of File Upload Widgets (with Initial Item) Sequence of I18N Sequence of Mapping Widgets Sequence of Mapping Widgets (with Initial Item) Sequence of Mappings (read-only) Sequence of Masked Text Inputs Sequence of Radio Choice Widgets Sequence of Rich Text Widgets Sequence of Sequence Widgets Text Area CSV Widget Text Area Widget Text Area Widget (read-only) Text Input CSV Widget Text Input Masks Text Input Widget Text Input Widget (read-only) Text Input Widget (with CSS class) Time Input Unicode Everywhere Widget Adapter

Demo: Deferred Schema Bindings

Blog post title

Blog post date (no earlier than Fri Dec 31 00:00:00 9999)

Blog post body (no longer than 5000 bytes)

Blog post category

Captured submission

None
    @view_config(renderer='templates/form.pt', name='deferred_schema_bindings')
    @demonstrate('Deferred Schema Bindings')
    def deferred_schema_bindings(self):
        import datetime
        import colander

        @colander.deferred
        def deferred_date_validator(node, kw):
            max_date = kw.get('max_date')
            if max_date is None:
                max_date = datetime.date.today()
            return colander.Range(min=datetime.date.min, max=max_date)

        @colander.deferred
        def deferred_date_description(node, kw):
            max_date = kw.get('max_date')
            if max_date is None:
                max_date = datetime.date.today()
            return 'Blog post date (no earlier than %s)' % max_date.ctime()

        @colander.deferred
        def deferred_date_missing(node, kw):
            default_date = kw.get('default_date')
            if default_date is None:
                default_date = datetime.date.today()
            return default_date

        @colander.deferred
        def deferred_body_validator(node, kw):
            max_bodylen = kw.get('max_bodylen')
            if max_bodylen is None:
                max_bodylen = 1 << 18
            return colander.Length(max=max_bodylen)

        @colander.deferred
        def deferred_body_description(node, kw):
            max_bodylen = kw.get('max_bodylen')
            if max_bodylen is None:
                max_bodylen = 1 << 18
            return 'Blog post body (no longer than %s bytes)' % max_bodylen

        @colander.deferred
        def deferred_body_widget(node, kw):
            body_type = kw.get('body_type')
            if body_type == 'richtext':
                widget = deform.widget.RichTextWidget()
            else:
                widget = deform.widget.TextAreaWidget()
            return widget

        @colander.deferred
        def deferred_category_validator(node, kw):
            categories = kw.get('categories', [])
            return colander.OneOf([x[0] for x in categories])

        @colander.deferred
        def deferred_category_widget(node, kw):
            categories = kw.get('categories', [])
            return deform.widget.RadioChoiceWidget(values=categories)

        class BlogPostSchema(colander.Schema):
            title = colander.SchemaNode(
                colander.String(),
                title='Title',
                description='Blog post title',
                validator=colander.Length(min=5, max=100),
                widget=deform.widget.TextInputWidget(),
                )
            date = colander.SchemaNode(
                colander.Date(),
                title='Date',
                missing=deferred_date_missing,
                description=deferred_date_description,
                validator=deferred_date_validator,
                widget=deform.widget.DateInputWidget(),
                )
            body = colander.SchemaNode(
                colander.String(),
                title='Body',
                description=deferred_body_description,
                validator=deferred_body_validator,
                widget=deferred_body_widget,
                )
            category = colander.SchemaNode(
                colander.String(),
                title='Category',
                description='Blog post category',
                validator=deferred_category_validator,
                widget=deferred_category_widget,
                )

        schema = BlogPostSchema().bind(
            max_date=datetime.date.max,
            max_bodylen=5000,
            body_type='richtext',
            default_date=datetime.date.today(),
            categories=[('one', 'One'), ('two', 'Two')]
            )

        form = deform.Form(schema, buttons=('submit',))
        return self.render_form(form)