Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

edelooff
Copy link

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

if part not in subset:
return False
subset = subset[part]
return True
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused by why you would need this? The errors should exist as {'foo.bar': error} not {'foo': {'bar': error}}. I can see why you would want it for renderer.value() since the data may be a nested dict if you are using variabledecode.

@edelooff
Copy link
Author

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
Copy link
Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants