diff options
author | Rogelio Mita <rogeliomita@activitycentral.com> | 2013-02-21 23:46:33 (GMT) |
---|---|---|
committer | Rogelio Mita <rogeliomita@activitycentral.com> | 2013-02-21 23:46:33 (GMT) |
commit | af9555f46d4bf605d52b13c415eb65352de773a8 (patch) | |
tree | cdfafaec0733bfccfe781ea161e7cfed4a7847ce | |
parent | 6470e0d404120530323b549ab1b0e4bcca06f8a2 (diff) |
Adding validation to widgets of fields.
-rw-r--r-- | webapp/polls/exceptions.py | 2 | ||||
-rw-r--r-- | webapp/polls/models.py | 50 | ||||
-rw-r--r-- | webapp/polls/templates/builder.html | 58 | ||||
-rw-r--r-- | webapp/polls/tests.py | 41 | ||||
-rw-r--r-- | webapp/polls/views.py | 5 |
5 files changed, 128 insertions, 28 deletions
diff --git a/webapp/polls/exceptions.py b/webapp/polls/exceptions.py new file mode 100644 index 0000000..15e676c --- /dev/null +++ b/webapp/polls/exceptions.py @@ -0,0 +1,2 @@ +class ValidationError(Exception): + pass diff --git a/webapp/polls/models.py b/webapp/polls/models.py index 2ab0f43..06c85b6 100644 --- a/webapp/polls/models.py +++ b/webapp/polls/models.py @@ -1,16 +1,22 @@ +# -*- encoding: utf-8 -*- import time +from exceptions import * + WIDGET_TYPES = ( - ('TextInput', 'TextInput'), - ('MultipleCheckbox', 'MultipleCheckbox'), - ('RadioButton', 'RadioButton'), - ('DropDownList', 'DropDownList'), + ('TextInput', 'Respuesta en texto'), + ('MultipleCheckbox', 'Respuesta con checks (multiple selección)'), + ('RadioButton', 'Respuesta con radios (Solo una selección)'), + ('DropDownList', 'Respuesta con lista de opciones'), ) class AbastractObject(object): + ValidationError = ValidationError + errors = [] + @staticmethod def get_offset_id(): return int(time.time() * 1000) @@ -36,6 +42,25 @@ class Option(AbastractObject): class Field(AbastractObject): + rules = { + 'MultipleCheckbox': ( + lambda f: len(f.options) > 0, + "Respuesta con checks (multiple selección): necesita " + "al menos una opción." + ), + 'RadioButton': ( + lambda f: len(f.options) > 1, + "Respuesta con radios (Solo una selección): necesita " + "al menos dos opciones." + ), + 'DropDownList': ( + lambda f: len(f.options) > 0, + "Respuesta con lista de opciones: necesita " + "al menos una opción." + ), + 'TextInput': (lambda f: True, ""), + } + def __init__(self, name, widget_type, key=None): super(Field, self).__init__() @@ -81,6 +106,13 @@ class Field(AbastractObject): def add_dependence(self, dependence): self.dependence = dependence + def validate(self): + self.errors = [] + rule, msg = Field.rules.get(self.widget_type) + if not rule(self): + self.errors.append(msg) + raise Field.ValidationError(msg) + class Group(AbastractObject): @@ -143,3 +175,13 @@ class Structure(object): self.groups = groups_pre + [group] + groups_post return group + + def is_valid(self): + valid = True + for group in self.groups: + for field in group.fields: + try: + field.validate() + except Field.ValidationError: + valid = False + return valid diff --git a/webapp/polls/templates/builder.html b/webapp/polls/templates/builder.html index 76f615e..fc8e298 100644 --- a/webapp/polls/templates/builder.html +++ b/webapp/polls/templates/builder.html @@ -5,40 +5,52 @@ <form class="form-inline" method="post" action=""> {% for group in structure.groups %} - <fieldset> + <fieldset class="well"> - <legend>{% trans group.name %}</legend> - - <input - type="hidden" + <legend> + <label><h3>Nombre del Grupo:</h3></label> + <input + type="text" name="groups.{{ forloop.counter0 }}.name" value="{{ group.name|default_if_none:'' }}" /> + </legend> {% for field in group.fields %} {% with group_index=forloop.parentloop.counter0 %} - <input - class="input-xxlarge" - type="text" - name="groups.{{ group_index }}.fields.{{ forloop.counter0 }}.name" - value="{{ field.name|default_if_none:'' }}" - placeholder="Pregunta..." - /> + {% if field.errors %} + <div class="control-group error"> + <label class="control-label">{{ field.errors.0 }}</label></br> + </div> + {% endif %} + + <div class="row-fluid"> + <input + class="input-xxlarge" + type="text" + name="groups.{{ group_index }}.fields.{{ forloop.counter0 }}.name" + value="{{ field.name|default_if_none:'' }}" + placeholder="Pregunta..." + /> - <select name="groups.{{ group_index }}.fields.{{ forloop.counter0 }}.widget_type"> + <select class="span3" name="groups.{{ group_index }}.fields.{{ forloop.counter0 }}.widget_type"> {% for k, v in WIDGET_TYPES %} <option value="{{ k }}" {% if k == field.widget_type %}selected="selected"{% endif %}>{{ v }}</option> {% endfor %} - </select> - - <input - class="input-mini" - type="text" - name=".groups.{{ group_index }}.fields.{{ field_index }}.options.{{ option.id }}.dependence" - value="{{ option.dependence|default_if_none:'' }}" - placeholder="dependence" - /> + </select> + </div> + + <div class="row-fluid"> + <label>Depende de la opción:</label> + <input + class="input-mini" + type="text" + name=".groups.{{ group_index }}.fields.{{ field_index }}.options.{{ option.id }}.dependence" + value="{{ option.dependence|default_if_none:'' }}" + placeholder="nro. ID" + /> + </div> {% if field.options %} <div class="control-group"> @@ -48,7 +60,7 @@ {% for option in field.options %} {% with field_index=forloop.parentloop.counter0 %} <div class="span3"> - <label>Opción {{ forloop.counter }}</label> + <label>Opción (ID: {{ option.id }})</label> <input class="input-large" type="text" diff --git a/webapp/polls/tests.py b/webapp/polls/tests.py index b6b898d..5499c00 100644 --- a/webapp/polls/tests.py +++ b/webapp/polls/tests.py @@ -1,3 +1,4 @@ +# -*- encoding: utf-8 -*- from django.test import TestCase from polls.models import Field, Group, Structure, Option, WIDGET_TYPES @@ -71,6 +72,23 @@ class FieldsTests(TestCase): self.assertEqual(1, len(field.options)) + def test_validate(self): + + self.field.widget_type = "MultipleCheckbox" + + self.assertRaises(Field.ValidationError, self.field.validate) + self.assertEqual(1, len(self.field.errors)) + + self.field.widget_type = "RadioButton" + + self.assertRaises(Field.ValidationError, self.field.validate) + self.assertEqual(1, len(self.field.errors)) + + self.field.widget_type = "DropDownList" + + self.assertRaises(Field.ValidationError, self.field.validate) + self.assertEqual(1, len(self.field.errors)) + class OptionTests(TestCase): @@ -171,3 +189,26 @@ class StructureTests(TestCase): field_1_1 = group_1.fields[1] self.assertEqual('field_1_1', field_1_1.name) self.assertEqual('DropDownList', field_1_1.widget_type) + + def test_is_valid(self): + data = { + 'groups': { + '0': { + 'name': 'group_0', + 'fields': { + '0': { + 'widget_type': 'RadioButton', + 'name': 'field_0_0' + }, + } + } + } + } + + structure = Structure(data=data) + + self.assertFalse(structure.is_valid()) + + field_0_0 = structure.groups[0].fields[0] + + self.assertEqual(1, len(field_0_0.errors)) diff --git a/webapp/polls/views.py b/webapp/polls/views.py index a2d4581..295103e 100644 --- a/webapp/polls/views.py +++ b/webapp/polls/views.py @@ -96,6 +96,9 @@ class BuilderView(TemplateView): data[key] = clean_data(value) structure = Structure(data={"groups": data['groups']}) - context.update({'structure': structure}) + if structure.is_valid(): + pass + + context.update({'structure': structure}) return self.render_to_response(context) |