def validate(self, validation_errors=None, related=False):
     validation_errors = super(Exam, self).validate(validation_errors) or {}
     # Verify that the passing score is from 0 to 100.
     if self.passing_score not in xrange(0, 101):
         pr_models.add_validation_error(validation_errors, 'passing_score', \
             'passing score must be from 0 to 100 inclusive')
     # Verify that the name field is set and unique among Exams.
     if not self.name:
         pr_models.add_validation_error(validation_errors, 'name',
                                        'exam must be given a name')
     possible_duplicates = Exam.objects.filter(name=self.name)
     if self.pk:
         possible_duplicates = possible_duplicates.exclude(pk=self.pk)
     for possible_duplicate in possible_duplicates:
         if self.version_id == possible_duplicate.version_id:
             pr_models.add_validation_error(validation_errors, 'name',
                 'exam with same name and version id exists')
     # make sure that the exam's name is not the name of any of its elements
     if not _name_is_unique(self,
         QuestionPool.objects.filter(exam=self) if self.pk else None,
         [Question.objects.filter(question_pool__exam=self),
         Answer.objects.filter(question__question_pool__exam=self),
         ] if self.pk is not None else []):
         pr_models.add_validation_error(validation_errors, 'name', \
             'exam name must not match the name of any of its elements')
     # When the related flag is set, validate all question pools that are
     # part of this exam.
     if related:
         for qp in self.question_pools.all():
             validation_errors = qp.validate(validation_errors, True)
     return validation_errors
Exemple #2
0
 def validate(self, validation_errors=None, related=False):
     validation_errors = super(Exam, self).validate(validation_errors) or {}
     # Verify that the passing score is from 0 to 100.
     if self.passing_score not in xrange(0, 101):
         pr_models.add_validation_error(validation_errors, 'passing_score', \
             'passing score must be from 0 to 100 inclusive')
     # Verify that the name field is set and unique among Exams.
     if not self.name:
         pr_models.add_validation_error(validation_errors, 'name',
                                        'exam must be given a name')
     possible_duplicates = Exam.objects.filter(name=self.name)
     if self.pk:
         possible_duplicates = possible_duplicates.exclude(pk=self.pk)
     for possible_duplicate in possible_duplicates:
         if self.version_id == possible_duplicate.version_id:
             pr_models.add_validation_error(
                 validation_errors, 'name',
                 'exam with same name and version id exists')
     # make sure that the exam's name is not the name of any of its elements
     if not _name_is_unique(
             self,
             QuestionPool.objects.filter(exam=self) if self.pk else None, [
                 Question.objects.filter(question_pool__exam=self),
                 Answer.objects.filter(question__question_pool__exam=self),
             ] if self.pk is not None else []):
         pr_models.add_validation_error(validation_errors, 'name', \
             'exam name must not match the name of any of its elements')
     # When the related flag is set, validate all question pools that are
     # part of this exam.
     if related:
         for qp in self.question_pools.all():
             validation_errors = qp.validate(validation_errors, True)
     return validation_errors
 def validate(self, validation_errors=None, related=False):
     validation_errors = super(QuestionPool, self).validate(validation_errors)
     validation_errors = validation_errors or {}
     if not _name_is_unique(self, QuestionPool.objects.filter(exam=self.exam),
                            [Exam.objects.filter(pk=self.exam.pk),
                             Question.objects.filter(question_pool__exam=self.exam),
                             Answer.objects.filter(question__question_pool__exam=self.exam),
                             ]):
         pr_models.add_validation_error(validation_errors,
             'name', 'value is not unique among the names in the current Exam')
     # Make sure the next_question_pool, if set, is part of the same exam.
     if self.next_question_pool and self.next_question_pool.exam != self.exam:
             pr_models.add_validation_error(validation_errors, \
                 'next_question_pool', \
                 'next question pool must be part of the same exam')
     # Make sure the next_question_pool does not put us in a loop.
     if self.next_question_pool and self.next_question_pool.order <= self.order:
             pr_models.add_validation_error(validation_errors, \
                 'next_question_pool', 'next question pool must come ' + \
                 'after the current question pool')
     # When the related flag is set, validate all questions that are part of
     # this question pool.
     if related:
         for q in self.questions.all():
             validation_errors = q.validate(validation_errors, True)
     return validation_errors
Exemple #4
0
 def validate(self, validation_errors=None):
     validation_errors = super(Answer, self).validate(validation_errors)
     validation_errors = validation_errors or {}
     exam = self.question.question_pool.exam
     if not _name_is_unique(
             self,
             Answer.objects.filter(question__question_pool__exam=exam), [
                 Exam.objects.filter(pk=exam.pk),
                 QuestionPool.objects.filter(exam=exam),
                 Question.objects.filter(question_pool__exam=exam),
             ]):
         pr_models.add_validation_error(
             validation_errors, 'name',
             'value is not unique among the names in the current Exam')
     # Make sure the next_question_pool, if set, is part of the same exam.
     if self.next_question_pool and \
         self.next_question_pool.exam != self.question.question_pool.exam:
         pr_models.add_validation_error(validation_errors, \
             'next_question_pool', \
             'next question pool must be part of the same exam')
     # Make sure the next_question_pool does not put us in a loop.
     if self.next_question_pool and \
         self.next_question_pool.order <= self.question.question_pool.order:
         pr_models.add_validation_error(validation_errors, \
             'next_question_pool', 'next question pool must come ' + \
             'after the current question pool')
     return validation_errors
Exemple #5
0
 def validate(self, validation_errors=None, related=False):
     validation_errors = super(QuestionPool,
                               self).validate(validation_errors)
     validation_errors = validation_errors or {}
     if not _name_is_unique(
             self, QuestionPool.objects.filter(exam=self.exam),
         [
             Exam.objects.filter(pk=self.exam.pk),
             Question.objects.filter(question_pool__exam=self.exam),
             Answer.objects.filter(question__question_pool__exam=self.exam),
         ]):
         pr_models.add_validation_error(
             validation_errors, 'name',
             'value is not unique among the names in the current Exam')
     # Make sure the next_question_pool, if set, is part of the same exam.
     if self.next_question_pool and self.next_question_pool.exam != self.exam:
         pr_models.add_validation_error(validation_errors, \
             'next_question_pool', \
             'next question pool must be part of the same exam')
     # Make sure the next_question_pool does not put us in a loop.
     if self.next_question_pool and self.next_question_pool.order <= self.order:
         pr_models.add_validation_error(validation_errors, \
             'next_question_pool', 'next question pool must come ' + \
             'after the current question pool')
     # When the related flag is set, validate all questions that are part of
     # this question pool.
     if related:
         for q in self.questions.all():
             validation_errors = q.validate(validation_errors, True)
     return validation_errors
 def validate(self, validation_errors=None):
     validation_errors = super(Answer, self).validate(validation_errors)
     validation_errors = validation_errors or {}
     exam = self.question.question_pool.exam
     if not _name_is_unique(self, Answer.objects.filter(question__question_pool__exam=exam),
                            [Exam.objects.filter(pk=exam.pk),
                             QuestionPool.objects.filter(exam=exam),
                             Question.objects.filter(question_pool__exam=exam),
                             ]):
         pr_models.add_validation_error(validation_errors,
             'name', 'value is not unique among the names in the current Exam')
     # Make sure the next_question_pool, if set, is part of the same exam.
     if self.next_question_pool and \
         self.next_question_pool.exam != self.question.question_pool.exam:
             pr_models.add_validation_error(validation_errors, \
                 'next_question_pool', \
                 'next question pool must be part of the same exam')
     # Make sure the next_question_pool does not put us in a loop.
     if self.next_question_pool and \
         self.next_question_pool.order <= self.question.question_pool.order:
             pr_models.add_validation_error(validation_errors, \
                 'next_question_pool', 'next question pool must come ' + \
                 'after the current question pool')
     return validation_errors
    def validate(self, validation_errors=None, related=False):
        validation_errors = super(Question, self).validate(validation_errors)
        validation_errors = validation_errors or {}
        
        # make sure that the name of this question is unique among all of the
        # name attributes for the question's Exam, and QuestionPools,
        # Questions, and Answers also belonging to the question's exam
        exam = self.question_pool.exam
        if not _name_is_unique(self, Question.objects.filter(question_pool__exam=exam),
                               [Exam.objects.filter(pk=exam.pk),
                                QuestionPool.objects.filter(exam=exam),
                                Answer.objects.filter(question__question_pool__exam=exam),
                                ]):
            pr_models.add_validation_error(validation_errors,
                'name', 'value is not unique among the names in the current Exam')

        # Verify range of values for numeric questions:
        if self.question_type in ('decimal', 'float', 'int', 'rating'):
            type_func = {'float': float, 'int': int, 'rating': int}.get( \
                self.question_type, lambda x: x)
            if self.min_value is not None and self.max_value is not None:
                if not type_func(self.max_value) >= type_func(self.min_value):
                    pr_models.add_validation_error(validation_errors, \
                        'max_value', \
                        'max_value must be greater than min_value')
        # Check minimum value for rating questions.
        if self.question_type == 'rating':
            if self.min_value is not None:
                if not int(self.min_value) >= 0:
                    pr_models.add_validation_error(validation_errors, \
                        'min_value', 'min_value must be zero or positive')
        # Check question attributes for a choice question.
        if self.question_type == 'choice':
            if self.max_answers is not None:
                if not self.max_answers >= self.min_answers:
                    pr_models.add_validation_error(validation_errors, \
                        'max_answers', \
                        'max_answers must be greater than min_answers')
                if not self.max_answers > 0:
                    pr_models.add_validation_error(validation_errors, \
                        'max_answers', 'max_answers must be greater than zero')
        # Verify text response length attributes.
        if self.max_length is not None:
            if not self.max_length >= self.min_length:
                pr_models.add_validation_error(validation_errors, 'max_length',\
                    'max_length must be greater than min_length')
        # Verify the text response regular expression.
        if self.text_regex is not None:
            try:
                re.compile(self.text_regex)
            except re.error:
                pr_models.add_validation_error(validation_errors, 'text_regex',\
                    'invalid text regular expression')
        # Use default widget for question type if not explicitly specified.
        if self.widget not in self.valid_widgets:
            pr_models.add_validation_error(validation_errors, 'widget', \
                'invalid widget %s for question type %s' % \
                (self.widget, self.question_type))
        # When the related flag is set, validate all answers that are part of
        # this question.
        if related:
            for a in self.answers.all():
                validation_errors = a.validate(validation_errors)
        return validation_errors
Exemple #8
0
    def validate(self, validation_errors=None, related=False):
        validation_errors = super(Question, self).validate(validation_errors)
        validation_errors = validation_errors or {}

        # make sure that the name of this question is unique among all of the
        # name attributes for the question's Exam, and QuestionPools,
        # Questions, and Answers also belonging to the question's exam
        exam = self.question_pool.exam
        if not _name_is_unique(
                self, Question.objects.filter(question_pool__exam=exam), [
                    Exam.objects.filter(pk=exam.pk),
                    QuestionPool.objects.filter(exam=exam),
                    Answer.objects.filter(question__question_pool__exam=exam),
                ]):
            pr_models.add_validation_error(
                validation_errors, 'name',
                'value is not unique among the names in the current Exam')

        # Verify range of values for numeric questions:
        if self.question_type in ('decimal', 'float', 'int', 'rating'):
            type_func = {'float': float, 'int': int, 'rating': int}.get( \
                self.question_type, lambda x: x)
            if self.min_value is not None and self.max_value is not None:
                if not type_func(self.max_value) >= type_func(self.min_value):
                    pr_models.add_validation_error(validation_errors, \
                        'max_value', \
                        'max_value must be greater than min_value')
        # Check minimum value for rating questions.
        if self.question_type == 'rating':
            if self.min_value is not None:
                if not int(self.min_value) >= 0:
                    pr_models.add_validation_error(validation_errors, \
                        'min_value', 'min_value must be zero or positive')
        # Check question attributes for a choice question.
        if self.question_type == 'choice':
            if self.max_answers is not None:
                if not self.max_answers >= self.min_answers:
                    pr_models.add_validation_error(validation_errors, \
                        'max_answers', \
                        'max_answers must be greater than min_answers')
                if not self.max_answers > 0:
                    pr_models.add_validation_error(validation_errors, \
                        'max_answers', 'max_answers must be greater than zero')
        # Verify text response length attributes.
        if self.max_length is not None:
            if not self.max_length >= self.min_length:
                pr_models.add_validation_error(validation_errors, 'max_length',\
                    'max_length must be greater than min_length')
        # Verify the text response regular expression.
        if self.text_regex is not None:
            try:
                re.compile(self.text_regex)
            except re.error:
                pr_models.add_validation_error(validation_errors, 'text_regex',\
                    'invalid text regular expression')
        # Use default widget for question type if not explicitly specified.
        if self.widget not in self.valid_widgets:
            pr_models.add_validation_error(validation_errors, 'widget', \
                'invalid widget %s for question type %s' % \
                (self.widget, self.question_type))
        # When the related flag is set, validate all answers that are part of
        # this question.
        if related:
            for a in self.answers.all():
                validation_errors = a.validate(validation_errors)
        return validation_errors