app/soc/views/helper/surveys.py
changeset 2501 d612b48e6e12
parent 2492 6eac6cd88dad
child 2502 2e096acc8720
--- a/app/soc/views/helper/surveys.py	Fri Jul 03 12:10:24 2009 +0200
+++ b/app/soc/views/helper/surveys.py	Fri Jul 03 14:19:23 2009 +0200
@@ -42,6 +42,7 @@
 
 from soc.logic import dicts
 from soc.logic.lists import Lists
+from soc.models.survey import COMMENT_PREFIX
 from soc.models.survey import SurveyContent
 
 
@@ -83,20 +84,26 @@
         pick_quant=self.addQuantField,
         )
 
+    self.kwargs['data'] = {}
     super(SurveyForm, self).__init__(*args, **self.kwargs)
 
-  def getFields(self):
+  def getFields(self, post_dict=None):
     """Build the SurveyContent (questions) form fields.
 
+    params:
+      post_dict: dict with POST data that will be used for validation
+
     Populates self.survey_fields, which will be ordered in self.insert_fields.
+    Also populates self.data, which will be used in form validation.
     """
 
     if not self.survey_content:
       return
 
+    post_dict = post_dict or {}
     self.survey_fields = {}
     schema = SurveyContentSchema(self.survey_content.schema)
-    has_record = (not self.editing) and self.survey_record
+    has_record = (not self.editing) and (self.survey_record or post_dict)
     extra_attrs = {}
 
     # figure out whether we want a read-only view
@@ -117,23 +124,51 @@
 
       # a comment made by the user
       comment = ''
-      if has_record and hasattr(self.survey_record, field):
+
+      # flag to know where the value came from
+      from_content = False
+
+      if has_record and field in post_dict:
+        # entered value that is not yet saved
+        value = post_dict[field]
+        if COMMENT_PREFIX + field in post_dict:
+          comment = post_dict[COMMENT_PREFIX + field]
+      elif has_record and hasattr(self.survey_record, field):
         # previously entered value
         value = getattr(self.survey_record, field)
-        if hasattr(self.survey_record, 'comment_for_' + field):
-          comment = getattr(self.survey_record, 'comment_for_' + field)
+        if hasattr(self.survey_record, COMMENT_PREFIX + field):
+          comment = getattr(self.survey_record, COMMENT_PREFIX + field)
       else:
         # use prompts set by survey creator
         value = getattr(self.survey_content, field)
+        from_content = True
 
       label = schema.getLabel(field)
       if label is None:
         continue
 
-      # dispatch to field-specific methods
+      # fix validation for pick_multi fields
+      is_multi = schema.getType(field) == 'pick_multi'
+      if not from_content and schema.getType(field) == 'pick_multi':
+        if isinstance(value, basestring):
+          value = value.split(',')
+      elif from_content and is_multi:
+        value = []
+
+      # record field value for validation
+      if not from_content:
+        self.data[field] = value
+
+      # find correct field type
       addField = self.fields_map[schema.getType(field)]
       addField(field, value, extra_attrs, schema, label=label, comment=comment)
 
+      # handle comments
+      comment_name = COMMENT_PREFIX + field
+      if comment_name in post_dict or hasattr(self.survey_record, comment_name):
+        self.data[comment_name] = comment
+        self.addCommentField(field, comment, extra_attrs, tip='Add a comment.')
+
     return self.insertFields()
 
   def insertFields(self):
@@ -147,9 +182,11 @@
       position = position * 2
       self.fields.insert(position, property, self.survey_fields[property])
       if not self.editing:
-        property = 'comment_for_' + property
-        self.fields.insert(position - 1, property,
-                           self.survey_fields[property])
+        # add comment if field has one and this isn't an edit view
+        property = COMMENT_PREFIX + property
+        if property in self.survey_fields:
+          self.fields.insert(position - 1, property,
+                             self.survey_fields[property])
     return self.fields
 
   def addLongField(self, field, value, attrs, schema, req=False, label='',
@@ -176,7 +213,6 @@
                          widget=widget, initial=value)
 
     self.survey_fields[field] = question
-    self.addCommentField(field, comment, attrs, tip)
 
   def addShortField(self, field, value, attrs, schema, req=False, label='',
                     tip='', comment=''):
@@ -203,7 +239,6 @@
                          widget=widget, max_length=140, initial=value)
 
     self.survey_fields[field] = question
-    self.addCommentField(field, comment, attrs, tip)
 
   def addSingleField(self, field, value, attrs, schema, req=False, label='',
                      tip='', comment=''):
@@ -240,7 +275,6 @@
                             choices=tuple(these_choices), widget=widget)
 
     self.survey_fields[field] = question
-    self.addCommentField(field, comment, attrs, tip)
 
   def addMultiField(self, field, value, attrs, schema, req=False, label='',
                     tip='', comment=''):
@@ -276,7 +310,6 @@
                              initial=value)
 
     self.survey_fields[field] = question
-    self.addCommentField(field, comment, attrs, tip)
 
   def addQuantField(self, field, value, attrs, schema, req=False, label='',
                     tip='', comment=''):
@@ -309,14 +342,13 @@
                              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',
+      comment_field = CharField(help_text=tip, required=False, label='Comments',
                           widget=widget, initial=comment)
-      self.survey_fields['comment_for_' + field] = comment
+      self.survey_fields[COMMENT_PREFIX + field] = comment_field
 
   class Meta(object):
     model = SurveyContent
@@ -606,10 +638,11 @@
       post_dict: dictionary with data from the POST request
   """
 
-  # TODO(ljvderijk) deal with the comment fields
+  # TODO(ljvderijk) deal with the comment fields neatly
 
   # get the schema for this survey
-  schema = eval(survey.survey_content.schema)
+  schema = SurveyContentSchema(survey.survey_content.schema)
+  schema_dict = schema.schema
 
   # fill a dictionary with the data to be stored in the SurveyRecord
   response_dict = {}
@@ -617,16 +650,25 @@
   for name, value in post_dict.items():
     # make sure name is a string
     name = name.encode()
-    if name not in schema:
+
+    if name not in schema_dict:
       # property not in survey schema ignore
       continue
     else:
-      pick_multi = schema[name]['type'] == 'pick_multi'
+      pick_multi = schema.getType(name) == 'pick_multi'
 
       if pick_multi and hasattr(post_dict, 'getlist'): # it's a multidict
-        response_dict[name] = ','.join(post_dict.getlist(name))
-      else:
-        response_dict[name] = value
+        # validation asks for a list of values
+        value = post_dict.getlist(name)
+
+    response_dict[name] = value
+
+    # handle comments
+    comment_name = COMMENT_PREFIX + name
+    if comment_name in post_dict:
+      comment = post_dict.get(comment_name)
+      if comment:
+        response_dict[comment_name] = comment
 
   return response_dict
 
@@ -796,16 +838,16 @@
     except StopIteration:
       # bail out early if survey_records.run() is empty
       return header, survey.link_id
-  
+
     # generate results list
     recs = record_query.run()
     recs = _get_records(recs, properties)
-  
+
     # write results to CSV
     output = StringIO.StringIO()
     writer = csv.writer(output)
     writer.writerow(properties)
     writer.writerows(recs)
-  
+
     return header + output.getvalue(), survey.link_id
   return wrapper