app/soc/views/models/grading_project_survey.py
author Daniel Diniz <ajaksu@gmail.com>
Sat, 04 Jul 2009 14:15:11 +0200
changeset 2527 ce657149b90a
parent 2513 c6de2d3eae90
child 2528 9de8348890d8
permissions -rw-r--r--
Add a grade field to the Grading Project Survey form. This also takes care of validating and transforming the data into True(pass) or False(fail). GradingProjectSurveys are hereby working for developers. Reviewed by: Lennard de Rijk

#!/usr/bin/python2.5
#
# Copyright 2009 the Melange authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Views for GradingProjectSurveys.
"""

__authors__ = [
  '"James Levy" <jamesalexanderlevy@gmail.com>',
  '"Lennard de Rijk" <ljvderijk@gmail.com>',
  ]

from django import forms

from soc.logic import dicts
from soc.logic.models.survey import GRADES
from soc.logic.models.survey import grading_logic as grading_survey_logic
from soc.views.helper import access
from soc.views.helper import decorators
from soc.views.helper import surveys
from soc.views.models import project_survey


class View(project_survey.View):
  """View methods for the GradingProjectSurvey model.
  """

  def __init__(self, params=None):
    """Defines the fields and methods required for the base View class
    to provide the user with list, public, create, edit and delete views.

    Params:
      params: a dict with params for this View
    """

    rights = access.Checker(params)
    rights['any_access'] = ['allow']
    rights['show'] = [('checkIsSurveyReadable', grading_survey_logic)]
    rights['create'] = ['checkIsUser']
    rights['edit'] = [('checkIsSurveyWritable', grading_survey_logic)]
    rights['delete'] = [('checkIsSurveyWritable', grading_survey_logic)]
    rights['list'] = ['checkDocumentList']
    rights['take'] = ['checkIsDeveloper'] # TODO(ljvderijk) add Project check

    new_params = {}
    new_params['logic'] = grading_survey_logic
    new_params['rights'] = rights

    new_params['name'] = "Grading Project Survey"

    params = dicts.merge(params, new_params, sub_merge=True)

    super(View, self).__init__(params=params)

  # TODO: work on grade activation
  def activate(self, request, **kwargs):
    """This is a hack to support the 'Enable grades' button.
    """
    self.activateGrades(request)
    redirect_path = request.path.replace('/activate/', '/edit/') + (
        '?activate=1')
    return http.HttpResponseRedirect(redirect_path)

  def activateGrades(self, request, **kwargs):
    """Updates SurveyRecord's grades for a given Survey.
    """
    survey_key_name = survey_logic.getKeyNameFromPath(request.path)
    survey = Survey.get_by_key_name(survey_key_name)
    survey_logic.activateGrades(survey)
    return

  def _getSurveyTakeForm(self, survey, record, params):
    """Returns the specific SurveyTakeForm needed for the take view.

    Args:
        survey: a Survey entity
        record: a SurveyRecord instance if any exist
        params: the params dict for the requesting View

    Returns:
        An instance of GradseSurveyTakeForm.
    """

    grade_choices = (('pass', 'Pass'), ('fail', 'Fail'))
    survey_form = GradeSurveyTakeForm(survey_content=survey.survey_content,
                                      survey_logic=params['logic'],
                                      grade_choices=grade_choices)

    return survey_form


class GradeSurveyTakeForm(surveys.SurveyTakeForm):
  """Extends SurveyTakeForm by adding a grade field.

  The grade field logic is dependent on the kwarg 'grade_choices' (behavior
  should be the same as the base class's if this argument is missing).
  """

  def __init__(self, *args, **kwargs):
    """Store grade choices and initialize the form.

    params:
      grade_choices: pair of tuples representing the grading choices
    """

    self.grade_choices = kwargs.pop('grade_choices', None)

    if self.grade_choices:
      # add grade field to self.data, respecting the data kwarg if present
      data = kwargs.pop('data', {})
      data['grade'] = None
      kwargs['data'] = data

    super(GradeSurveyTakeForm, self).__init__(*args, **kwargs)

  def clean_grade(self):
    """Validate the grade field.
    """

    grade = self.cleaned_data['grade']

    # map to bool
    grade_vals = {'pass': True, 'fail': False, '': ''}

    return grade_vals.get(grade, None)

  def getFields(self, post_dict=None):
    """Add the extra grade field's value from POST or survey_record.

    Args:
        post_dict: dict with POST data if exists
    """

    # fetch value from post_dict if it's there
    post_dict = post_dict or {}
    grade = post_dict.get('grade', None)

    # otherwise, try to fetch from survey_record
    if not grade and hasattr(self.survey_record, 'grade'):
      grade = self.survey_record.grade

    # remap bool to string values as the ChoiceField validates on 'choices'.
    vals_grade = {True: 'pass', False: 'fail'}

    if self.grade_choices:
      self.data['grade'] = vals_grade.get(grade, None) or grade

    super(GradeSurveyTakeForm, self).getFields(post_dict)

  def insertFields(self):
    """Add ordered fields to self.fields, add grade field with grade choices.
    """

    # add common survey fields
    super(GradeSurveyTakeForm, self).insertFields()

    if self.grade_choices:
      # add empty option to choices
      grade_choices = (('', "Choose a Grade"),) + tuple(self.grade_choices)

      gradeField = forms.fields.ChoiceField(choices=grade_choices,
                                            required=True,
                                            widget=forms.Select())
      # add the grade field at the form's bottom
      self.fields.insert(len(self.fields) + 1, 'grade', gradeField)

    return self.fields


view = View()

create = decorators.view(view.create)
edit = decorators.view(view.edit)
delete = decorators.view(view.delete)
list = decorators.view(view.list)
public = decorators.view(view.public)
take = decorators.view(view.take)