From 3abf20f332a641bf84ce5692b31b96cf4c630ce2 Mon Sep 17 00:00:00 2001 From: Elmer de Looff Date: Thu, 10 Oct 2013 22:25:23 +0200 Subject: [PATCH 1/3] Added support for nested schemas which use dotted notation for is_error. Renderer.is_error now delegates to Form.is_error which implements the nested dictionary traversal. --- pyramid_simpleform/__init__.py | 37 ++++++++------ pyramid_simpleform/renderers.py | 86 ++++++++++++++++----------------- 2 files changed, 65 insertions(+), 58 deletions(-) diff --git a/pyramid_simpleform/__init__.py b/pyramid_simpleform/__init__.py index b5aff63..be5f2f9 100644 --- a/pyramid_simpleform/__init__.py +++ b/pyramid_simpleform/__init__.py @@ -76,15 +76,15 @@ class Form(object): `list_char` : variabledecode list char Also note that values of ``obj`` supercede those of ``defaults``. Only - fields specified in your schema or validators will be taken from the + fields specified in your schema or validators will be taken from the object. """ default_state = State - def __init__(self, request, schema=None, validators=None, defaults=None, - obj=None, extra=None, include=None, exclude=None, state=None, - method="POST", variable_decode=False, dict_char=".", + def __init__(self, request, schema=None, validators=None, defaults=None, + obj=None, extra=None, include=None, exclude=None, state=None, + method="POST", variable_decode=False, dict_char=".", list_char="-", multipart=False): self.request = request @@ -120,7 +120,16 @@ def __init__(self, request, schema=None, validators=None, defaults=None, def is_error(self, field): """ Checks if individual field has errors. + + Traverses nested forms when dotted notation is provided. """ + if '.' in field: + subset = self.errors + for part in field.split('.'): + if part not in subset: + return False + subset = subset[part] + return True return field in self.errors def all_errors(self): @@ -147,13 +156,13 @@ def errors_for(self, field): def validate(self, force_validate=False, params=None): """ - Runs validation and returns True/False whether form is + Runs validation and returns True/False whether form is valid. - + This will check if the form should be validated (i.e. the request method matches) and the schema/validators validate. - Validation will only be run once; subsequent calls to + Validation will only be run once; subsequent calls to validate() will have no effect, i.e. will just return the original result. @@ -161,7 +170,7 @@ def validate(self, force_validate=False, params=None): `force_validate` : will run validation regardless of request method. - `params` : dict or MultiDict of params. By default + `params` : dict or MultiDict of params. By default will use **request.POST** (if HTTP POST) or **request.params**. """ @@ -180,7 +189,7 @@ def validate(self, force_validate=False, params=None): params = self.request.POST else: params = self.request.params - + if self.variable_decode: decoded = variabledecode.variable_decode( params, self.dict_char, self.list_char) @@ -216,10 +225,10 @@ def bind(self, obj, include=None, exclude=None): Binds validated field values to an object instance, for example a SQLAlchemy model instance. - `include` : list of included fields. If field not in this list it + `include` : list of included fields. If field not in this list it will not be bound to this object. - `exclude` : list of excluded fields. If field is in this list it + `exclude` : list of excluded fields. If field is in this list it will not be bound to the object. Returns the `obj` passed in. @@ -258,7 +267,7 @@ def htmlfill(self, content, **htmlfill_kwargs): charset = getattr(self.request, 'charset', 'utf-8') htmlfill_kwargs.setdefault('encoding', charset) - return htmlfill.render(content, + return htmlfill.render(content, defaults=self.data, errors=self.errors, **htmlfill_kwargs) @@ -267,7 +276,7 @@ def render(self, template, extra_info=None, htmlfill=True, **htmlfill_kwargs): """ Renders the form directly to a template, - using Pyramid's **render** function. + using Pyramid's **render** function. `template` : name of template @@ -292,7 +301,7 @@ def submit(request): return dict(form=form.render("my_form.html")) """ - + extra_info = extra_info or {} extra_info.setdefault('form', self) diff --git a/pyramid_simpleform/renderers.py b/pyramid_simpleform/renderers.py index 7d4c95c..29c9661 100644 --- a/pyramid_simpleform/renderers.py +++ b/pyramid_simpleform/renderers.py @@ -29,9 +29,9 @@ def text(self, name, value=None, id=None, **attrs): Outputs text input. """ return tags.text( - name, - self.value(name, value), - self._get_id(id, name), + name, + self.value(name, value), + self._get_id(id, name), **attrs ) @@ -40,9 +40,9 @@ def file(self, name, value=None, id=None, **attrs): Outputs file input. """ return tags.file( - name, - self.value(name, value), - self._get_id(id, name), + name, + self.value(name, value), + self._get_id(id, name), **attrs ) @@ -54,9 +54,9 @@ def hidden(self, name, value=None, id=None, **attrs): value = self.value(name) return tags.hidden( - name, - value, - self._get_id(id, name), + name, + value, + self._get_id(id, name), **attrs ) @@ -72,9 +72,9 @@ def submit(self, name, value=None, id=None, **attrs): Outputs submit button. """ return tags.submit( - name, - self.value(name, value), - self._get_id(id, name), + name, + self.value(name, value), + self._get_id(id, name), **attrs ) @@ -83,25 +83,25 @@ def select(self, name, options, selected_value=None, id=None, **attrs): Outputs