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(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
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(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
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