From d9793c01304498d7f59820cf2ab2d7a5483851f8 Mon Sep 17 00:00:00 2001 From: prathamesh Date: Wed, 2 Mar 2016 15:48:39 +0530 Subject: Course module implemented Moderator can now create courses. Under his courses he can create quizzes. Students can enroll for the course. Moderator can approve or reject enrollment request of the student. Student can view quizzes only for the enrolled course. --- yaksh/forms.py | 17 +++- yaksh/models.py | 67 ++++++++++++++ yaksh/static/yaksh/css/course.css | 18 ++++ yaksh/static/yaksh/css/question_quiz.css | 3 + yaksh/templates/manage.html | 6 +- yaksh/templates/yaksh/add_course.html | 21 +++++ yaksh/templates/yaksh/add_quiz.html | 2 +- yaksh/templates/yaksh/course_detail.html | 59 ++++++++++++ yaksh/templates/yaksh/courses.html | 39 ++++++++ yaksh/templates/yaksh/quizzes_user.html | 153 +++++++++++++++++++------------ yaksh/urls.py | 12 +++ yaksh/views.py | 121 ++++++++++++++++++++++-- 12 files changed, 441 insertions(+), 77 deletions(-) create mode 100644 yaksh/static/yaksh/css/course.css create mode 100644 yaksh/templates/yaksh/add_course.html create mode 100644 yaksh/templates/yaksh/course_detail.html create mode 100644 yaksh/templates/yaksh/courses.html diff --git a/yaksh/forms.py b/yaksh/forms.py index de40419..1af02f7 100644 --- a/yaksh/forms.py +++ b/yaksh/forms.py @@ -1,5 +1,5 @@ from django import forms -from yaksh.models import Profile, Quiz, Question, TestCase +from yaksh.models import Profile, Quiz, Question, TestCase, Course from django.contrib.auth import authenticate from django.contrib.auth.models import User @@ -132,12 +132,15 @@ class QuizForm(forms.Form): It has the related fields and functions required.""" def __init__(self, *args, **kwargs): + user = kwargs.pop('user') super(QuizForm, self).__init__(*args, **kwargs) quizzes = [('', 'Select a prerequisite quiz')] - quizzes = quizzes + \ - list(Quiz.objects.values_list('id', 'description')) + quizzes += list(Quiz.objects.filter( + course__creator=user).values_list('id', 'description')) self.fields['prerequisite'] = forms.CharField(required=False, widget=forms.Select(choices=quizzes)) + self.fields['course'] = forms.ModelChoiceField( + queryset=Course.objects.filter(creator=user)) start_date = forms.DateField(initial=datetime.date.today(), required=False) start_time = forms.TimeField(initial=datetime.datetime.now().time(), required=False) @@ -156,6 +159,7 @@ class QuizForm(forms.Form): help_text='Will be in days') def save(self): + course = self.cleaned_data["course"] start_date = self.cleaned_data["start_date"] start_time = self.cleaned_data["start_time"] end_date = self.cleaned_data["end_date"] @@ -169,6 +173,7 @@ class QuizForm(forms.Form): attempts_allowed = self.cleaned_data["attempts_allowed"] time_between_attempts = self.cleaned_data["time_between_attempts"] new_quiz = Quiz() + new_quiz.course = course new_quiz.start_date_time = datetime.datetime.combine(start_date, start_time) new_quiz.end_date_time = datetime.datetime.combine(end_date, @@ -265,3 +270,9 @@ class QuestionFilterForm(forms.Form): TestCaseFormSet = inlineformset_factory(Question, TestCase,\ can_order=False, can_delete=False, extra=1) + + +class CourseForm(forms.ModelForm): + class Meta: + model = Course + fields = ['name', 'active', 'enrollment'] diff --git a/yaksh/models.py b/yaksh/models.py index 8415930..d6fe972 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -40,6 +40,12 @@ question_types = ( ("code", "Code"), ("upload", "Assignment Upload"), ) + +enrollment_methods = ( + ("default", "Enroll Request"), + ("open", "Open Course"), + ) + attempts = [(i, i) for i in range(1, 6)] attempts.append((-1, 'Infinite')) days_between_attempts = ((j, j) for j in range(401)) @@ -54,6 +60,65 @@ def get_assignment_dir(instance, filename): return '%s/%s' % (instance.user.roll_number, instance.assignmentQuestion.id) +############################################################################### +class Course(models.Model): + name = models.CharField(max_length=128) + enrollment = models.CharField(max_length=32, choices=enrollment_methods) + active = models.BooleanField(default=True) + creator = models.ForeignKey(User, related_name='creator') + students = models.ManyToManyField(User, related_name='students') + requests = models.ManyToManyField(User, related_name='requests') + rejected = models.ManyToManyField(User, related_name='rejected') + created_on = models.DateTimeField(default=datetime.datetime.now()) + + def request(self, *users): + self.requests.add(*users) + + def get_requests(self): + return self.requests.all() + + def reject(self, was_enrolled=False, *users): + self.rejected.add(*users) + if not was_enrolled: + self.requests.remove(*users) + else: + self.students.remove(*users) + + def get_rejected(self): + return self.rejected.all() + + def enroll(self, was_rejected=False, *users): + self.students.add(*users) + if not was_rejected: + self.requests.remove(*users) + else: + self.rejected.remove(*users) + + def get_enrolled(self): + return self.students.all() + + def is_enrolled(self, user_id): + return self.students.filter(id=user_id).exists() + + def is_creator(self, user): + return self.creator == user + + def get_quizzes(self): + return self.quiz_set.all() + + def activate(self): + self.active = True + + def deactivate(self): + self.active = False + + def is_self_enroll(self): + return True if self.enrollment == 'open' else False + + def __unicode__(self): + return self.name + + ############################################################################### class Question(models.Model): """Question for a quiz.""" @@ -166,6 +231,8 @@ class Quiz(models.Model): as the "examination" event. """ + course = models.ForeignKey(Course) + # The start date of the quiz. start_date_time = models.DateTimeField("Start Date and Time of the quiz", default=datetime.datetime.now(), diff --git a/yaksh/static/yaksh/css/course.css b/yaksh/static/yaksh/css/course.css new file mode 100644 index 0000000..580a95c --- /dev/null +++ b/yaksh/static/yaksh/css/course.css @@ -0,0 +1,18 @@ +.show-grid [class*="span"] { + background: none repeat scroll 0% 0% #EEE; + text-align: center; + border-radius: 10px; + min-height: 30px; + line-height: 30px; + padding: 5px; +} + +.well{ + padding: 4px; +} + +.wrap{ + border: 1px solid #333; + padding: 5px; + background: none repeat scroll 0% 0% #E0DADA; +} diff --git a/yaksh/static/yaksh/css/question_quiz.css b/yaksh/static/yaksh/css/question_quiz.css index ee249d4..26dc42b 100644 --- a/yaksh/static/yaksh/css/question_quiz.css +++ b/yaksh/static/yaksh/css/question_quiz.css @@ -22,3 +22,6 @@ table th, table td height : 30px; width : 100px; } +input, textarea, select, .uneditable-input { + height: 30px; +} diff --git a/yaksh/templates/manage.html b/yaksh/templates/manage.html index ca2ac65..11e2187 100644 --- a/yaksh/templates/manage.html +++ b/yaksh/templates/manage.html @@ -27,9 +27,9 @@

Online Test