Added SurveyContentSchema to improve readability for the survey helper.
authorDaniel Diniz <ajaksu@gmail.com>
Mon, 29 Jun 2009 19:29:15 +0200
changeset 2451 c58a7ea6c126
parent 2450 596fad6da0e1
child 2452 4abc27894b61
Added SurveyContentSchema to improve readability for the survey helper. Reviewed by: Lennard de Rijk
app/soc/views/helper/surveys.py
--- a/app/soc/views/helper/surveys.py	Mon Jun 29 16:51:48 2009 +0200
+++ b/app/soc/views/helper/surveys.py	Mon Jun 29 19:29:15 2009 +0200
@@ -66,23 +66,21 @@
     """
 
     self.kwargs = kwargs
-    self.survey_content = self.kwargs.get('survey_content', None)
-    self.this_user = self.kwargs.get('this_user', None)
-    self.project = self.kwargs.get('project', None)
-    self.survey_record = self.kwargs.get('survey_record', None)
+    self.survey_content = self.kwargs.pop('survey_content', None)
+    self.this_user = self.kwargs.pop('this_user', None)
+    self.project = self.kwargs.pop('project', None)
+    self.survey_record = self.kwargs.pop('survey_record', None)
+
+    self.read_only = self.kwargs.pop('read_only', None)
+    self.editing = self.kwargs.pop('editing', None)
 
-    del self.kwargs['survey_content']
-    del self.kwargs['this_user']
-    del self.kwargs['project']
-    del self.kwargs['survey_record']
-
-    self.read_only = self.kwargs.get('read_only', None)
-    if 'read_only' in self.kwargs:
-      del self.kwargs['read_only']
-
-    self.editing = self.kwargs.get('editing', None)
-    if 'editing' in self.kwargs:
-      del self.kwargs['editing']
+    self.fields_map = dict(
+        long_answer=self.addLongField,
+        short_answer=self.addShortField,
+        selection=self.addSingleField,
+        pick_multi=self.addMultiField,
+        pick_quant=self.addQuantField,
+        )
 
     super(SurveyForm, self).__init__(*args, **self.kwargs)
 
@@ -125,31 +123,13 @@
         # use prompts set by survey creator
         value = getattr(self.survey_content, field)
 
-      if field not in schema:
-        logging.error('field %s not found in schema %s' %
-        (field, str(schema) ) )
-        continue 
-      elif 'question' in schema[field]:
-        label = schema[field].get('question', None) or field
-      else:
-        label = field
+      label = schema.getLabel(field)
+      if label is None:
+        continue
 
       # dispatch to field-specific methods
-      if schema[field]["type"] == "long_answer":
-        self.addLongField(field, value, extra_attrs, label=label,
-                          comment=comment)
-      elif schema[field]["type"] == "short_answer":
-        self.addShortField(field, value, extra_attrs, label=label,
-                           comment=comment)
-      elif schema[field]["type"] == "selection":
-        self.addSingleField(field, value, extra_attrs, schema, label=label,
-                            comment=comment)
-      elif schema[field]["type"] == "pick_multi":
-        self.addMultiField(field, value, extra_attrs, schema, label=label,
-                           comment=comment)
-      elif schema[field]["type"] == "pick_quant":
-        self.addQuantField(field, value, extra_attrs, schema, label=label,
-                           comment=comment)
+      addField = self.fields_map[schema.getType(field)]
+      addField(field, value, extra_attrs, schema, label=label, comment=comment)
 
     return self.insertFields()
 
@@ -169,7 +149,7 @@
                            self.survey_fields[property])
     return self.fields
 
-  def addLongField(self, field, value, attrs, req=False, label='', tip='',
+  def addLongField(self, field, value, attrs, schema, req=False, label='', tip='',
                    comment=''):
     """Add a long answer fields to this form.
 
@@ -177,10 +157,11 @@
       field: the current field
       value: the initial value for this field
       attrs: additional attributes for field
+      schema: schema for survey
       req: required bool
       label: label for field
       tip: tooltip text for field
-      comment: initial comment value for field 
+      comment: initial comment value for field
     """
 
     widget = widgets.Textarea(attrs=attrs)
@@ -190,15 +171,11 @@
 
     question = CharField(help_text=tip, required=req, label=label,
                          widget=widget, initial=value)
-    self.survey_fields[field] = question
 
-    if not self.editing:
-      widget = widgets.Textarea(attrs=attrs)
-      comment = CharField(help_text=tip, required=False, label='Comments',
-                          widget=widget, initial=comment)
-      self.survey_fields['comment_for_' + field] = comment
+    self.survey_fields[field] = question
+    self.addCommentField(field, comment, attrs, tip)
 
-  def addShortField(self, field, value, attrs, req=False, label='', tip='',
+  def addShortField(self, field, value, attrs, schema, req=False, label='', tip='',
                     comment=''):
     """Add a short answer fields to this form.
 
@@ -206,10 +183,11 @@
       field: the current field
       value: the initial value for this field
       attrs: additional attributes for field
+      schema: schema for survey
       req: required bool
       label: label for field
       tip: tooltip text for field
-      comment: initial comment value for field 
+      comment: initial comment value for field
     """
 
     attrs['class'] = "text_question"
@@ -220,13 +198,9 @@
 
     question = CharField(help_text=tip, required=req, label=label,
                          widget=widget, max_length=140, initial=value)
+
     self.survey_fields[field] = question
-
-    if not self.editing:
-      widget = widgets.Textarea(attrs=attrs)
-      comment = CharField(help_text=tip, required=False, label='Comments',
-                          widget=widget, initial=comment)
-      self.survey_fields['comment_for_' + field] = comment
+    self.addCommentField(field, comment, attrs, tip)
 
   def addSingleField(self, field, value, attrs, schema, req=False, label='',
                      tip='', comment=''):
@@ -243,12 +217,7 @@
       comment: initial comment value for field
     """
 
-    if self.editing:
-      kind = schema[field]["type"]
-      render = schema[field]["render"]
-      widget = UniversalChoiceEditor(kind, render)
-    else:
-      widget = WIDGETS[schema[field]['render']](attrs=attrs)
+    widget = schema.getWidget(field, self.editing, attrs)
 
     these_choices = []
     # add all properties, but select chosen one
@@ -266,13 +235,9 @@
 
     question = PickOneField(help_text=tip, required=req, label=label,
                             choices=tuple(these_choices), widget=widget)
+
     self.survey_fields[field] = question
-
-    if not self.editing:
-      widget = widgets.Textarea(attrs=attrs)
-      comment = CharField(help_text=tip, required=False, label='Comments',
-                          widget=widget, initial=comment)
-      self.survey_fields['comment_for_' + field] = comment
+    self.addCommentField(field, comment, attrs, tip)
 
   def addMultiField(self, field, value, attrs, schema, req=False, label='',
                     tip='', comment=''):
@@ -287,14 +252,10 @@
       label: label for field
       tip: tooltip text for field
       comment: initial comment value for field
+
     """
 
-    if self.editing:
-      kind = schema[field]["type"]
-      render = schema[field]["render"]
-      widget = UniversalChoiceEditor(kind, render)
-    else:
-      widget = WIDGETS[schema[field]['render']](attrs=attrs)
+    widget = schema.getWidget(field, self.editing, attrs)
 
     # TODO(ajaksu) need to allow checking checkboxes by default
     if self.survey_record and isinstance(value, basestring):
@@ -310,12 +271,9 @@
     question = PickManyField(help_text=tip, required=req, label=label,
                              choices=tuple(these_choices), widget=widget,
                              initial=value)
+
     self.survey_fields[field] = question
-    if not self.editing:
-      widget = widgets.Textarea(attrs=attrs)
-      comment = CharField(help_text=tip, required=False, label='Comments',
-                          widget=widget, initial=comment)
-      self.survey_fields['comment_for_' + field] = comment
+    self.addCommentField(field, comment, attrs, tip)
 
   def addQuantField(self, field, value, attrs, schema, req=False, label='',
                     tip='', comment=''):
@@ -330,14 +288,10 @@
       label: label for field
       tip: tooltip text for field
       comment: initial comment value for field
+
     """
 
-    if self.editing:
-      kind = schema[field]["type"]
-      render = schema[field]["render"]
-      widget = UniversalChoiceEditor(kind, render)
-    else:
-      widget = WIDGETS[schema[field]['render']](attrs=attrs)
+    widget = schema.getWidget(field, self.editing, attrs)
 
     if self.survey_record:
       value = value
@@ -352,18 +306,60 @@
                              choices=tuple(these_choices), widget=widget,
                              initial=value)
     self.survey_fields[field] = question
+    self.addCommentField(field, comment, attrs, tip)
+
+  def addCommentField(self, field, comment, attrs, tip):
     if not self.editing:
       widget = widgets.Textarea(attrs=attrs)
       comment = CharField(help_text=tip, required=False, label='Comments',
                           widget=widget, initial=comment)
       self.survey_fields['comment_for_' + field] = comment
 
-
   class Meta(object):
     model = SurveyContent
     exclude = ['schema']
 
 
+class SurveyContentSchema(object):
+  """Abstract question metadata handling.
+  """
+
+  def __init__(self, schema):
+    self.schema = eval(schema)
+
+  def getType(self, field):
+    return self.schema[field]["type"]
+
+  def getRender(self, field):
+    return self.schema[field]["render"]
+
+  def getWidget(self, field, editing, attrs):
+    """Get survey editing or taking widget for choice questions.
+    """
+
+    if editing:
+      kind = self.getType(field)
+      render = self.getRender(field)
+      widget = UniversalChoiceEditor(kind, render)
+    else:
+      widget = WIDGETS[self.schema[field]['render']](attrs=attrs)
+    return widget
+
+  def getLabel(self, field):
+    """Fetch the free text 'question' or use field name as label.
+    """
+
+    if field not in self.schema:
+      logging.error('field %s not found in schema %s' %
+                    (field, str(self.schema)))
+      return
+    elif 'question' in self.schema[field]:
+      label = self.schema[field].get('question') or field
+    else:
+      label = field
+    return label
+
+
 class UniversalChoiceEditor(widgets.Widget):
   """Edit interface for choice questions.
 
@@ -600,9 +596,9 @@
 def getRoleSpecificFields(survey, user, this_project, survey_form,
                           survey_record):
   """For evaluations, mentors get required Project and Grade fields, and
-  students get a required Project field. 
+  students get a required Project field.
 
-  Because we need to get a list of the user's projects, we call the 
+  Because we need to get a list of the user's projects, we call the
   logic getProjects method, which doubles as an access check.
   (No projects means that the survey cannot be taken.)
 
@@ -615,11 +611,10 @@
       or None
   """
 
-  from django import forms
-
   field_count = len(eval(survey.survey_content.schema).items())
   these_projects = survey_logic.getProjects(survey, user)
-  if not these_projects: return False # no projects found
+  if not these_projects:
+    return False # no projects found
 
   project_pairs = []
   #insert a select field with options for each project