pyramid_simpleform icon indicating copy to clipboard operation
pyramid_simpleform copied to clipboard

Added support for nested schemas which use dotted notation for is_error.

Open edelooff opened this issue 12 years ago • 2 comments

Renderer.is_error now delegates to Form.is_error which implements the nested dictionary traversal.

Apologies for the massive ton of white-space differences introduced by the editor. The actual changes happen near line 120 in init.py and line 133 in renderers.py

edelooff avatar Oct 10 '13 20:10 edelooff

I'll have to test this again to be sure but I ran into the problem where my error dict was also nested. Maybe I was merely seeing things though. I should have some time to check this over the weekend, confirm what I ran into.

edelooff avatar Oct 18 '13 14:10 edelooff

Hi Chris,

Sorry for taking forever to get back to you. I got back to using nested forms earlier today and worked myself into the same corner again, so I'll try to elaborate on the problem and hopefully explain my suggested solution.

I'm using a nested schema structure like this:

class Address(formencode.Schema):
    allow_extra_fields = True
    filter_extra_fields = True

    name_line = validators.UnicodeString(not_empty=True, max=64)
    street = validators.UnicodeString(not_empty=True, max=50)
    number = validators.Int(not_empty=True)
    number_addition = validators.UnicodeString(max=10)
    postal_code = DutchPostalCode(not_empty=True)
    city = validators.UnicodeString(not_empty=True)

class Claim(formencode.Schema):
    allow_extra_fields = True
    filter_extra_fields = True
    pre_validators = [formencode.variabledecode.NestedVariables]

    address = Address  # Re-use the address schema defined previously
    properties = validators.UnicodeString(not_empty=True, max=500)
    completed = validators.StringBool(if_missing=False)

This is rendered in a Mako template:

<fieldset>
  ${form.label('address.name_line')}
  ${form.text('address.name_line')}
  ...
  ${form.label('address.city')}
  ${form.text('address.city')}
</fieldset>
<fieldset>
  ${form.label('properties')}
  ${form.textarea('properties')}
  ...
</fieldset>

When I fill out the complete address according to the schema requirements, the value lookups for the address don't work and the address remains empty and I only get visible errors for the missing properties. This is the part you acknowledged and which is (partly) fixed by this pull request.

The following is taken from the pyramid debugging console after leaving the properties field and all address parts empty:

>>> form.form.errors
{
    'properties': u'Please enter a value',
    'address': {
        'city': u'Please enter a value',
        'name_line': u'Please enter a value',
        'street': u'Please enter a value',
        'number': u'Please enter a value',
        'postal_code': u'Please enter a value'
    }
}

>>> form.errors_for('properties')
[
    u'Please enter a value'
]

>>> form.errors_for('address')
{
    'city': u'Please enter a value',
    'name_line': u'Please enter a value',
    'street': u'Please enter a value',
    'number': u'Please enter a value',
    'postal_code': u'Please enter a value'
}

From my understanding, after variabledecode has done its work, the errors are also in the nested structure instead of the flat one. This also causes inconsistent behaviour with other functions that use errors such as errors_for, which should return a list but returns a dictionary after the unflattening performed by variabledecode.

Please point out if I'm doing something weird or unusual here, or if you need more information from my end.

edelooff avatar Dec 19 '13 16:12 edelooff