summaryrefslogtreecommitdiff
path: root/yaksh/views.py
diff options
context:
space:
mode:
Diffstat (limited to 'yaksh/views.py')
-rw-r--r--yaksh/views.py920
1 files changed, 628 insertions, 292 deletions
diff --git a/yaksh/views.py b/yaksh/views.py
index ecd7efd..b54461f 100644
--- a/yaksh/views.py
+++ b/yaksh/views.py
@@ -6,17 +6,21 @@ from django.shortcuts import render, get_object_or_404, redirect
from django.template import Context, Template
from django.http import Http404
from django.db.models import Max, Q, F
+from django.db import models
from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import Group
from django.forms.models import inlineformset_factory
+from django.forms import fields
from django.utils import timezone
from django.core.exceptions import (
MultipleObjectsReturned, ObjectDoesNotExist
)
+from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
+from django.contrib import messages
from taggit.models import Tag
+from django.urls import reverse
import json
-import six
from textwrap import dedent
import zipfile
from markdown import Markdown
@@ -28,16 +32,19 @@ import re
# Local imports.
from yaksh.code_server import get_result as get_result_from_code_server
from yaksh.models import (
- Answer, AnswerPaper, AssignmentUpload, Course, FileUpload, Profile,
- QuestionPaper, QuestionSet, Quiz, Question, TestCase, User,
- FIXTURES_DIR_PATH, MOD_GROUP_NAME, Lesson, LessonFile, LearningUnit, LearningModule,
- CourseStatus
+ Answer, AnswerPaper, AssignmentUpload, Course, FileUpload, FloatTestCase,
+ HookTestCase, IntegerTestCase, McqTestCase, Profile,
+ QuestionPaper, QuestionSet, Quiz, Question, StandardTestCase,
+ StdIOBasedTestCase, StringTestCase, TestCase, User,
+ get_model_class, FIXTURES_DIR_PATH, MOD_GROUP_NAME, Lesson, LessonFile,
+ LearningUnit, LearningModule, CourseStatus, question_types
)
from yaksh.forms import (
UserRegisterForm, UserLoginForm, QuizForm, QuestionForm,
QuestionFilterForm, CourseForm, ProfileForm,
UploadFileForm, FileForm, QuestionPaperForm, LessonForm,
- LessonFileForm, LearningModuleForm, ExerciseForm
+ LessonFileForm, LearningModuleForm, ExerciseForm, TestcaseForm,
+ SearchFilterForm
)
from yaksh.settings import SERVER_POOL_PORT, SERVER_HOST_NAME
from .settings import URL_ROOT
@@ -77,7 +84,7 @@ def is_moderator(user, group_name=MOD_GROUP_NAME):
def add_as_moderator(users, group_name=MOD_GROUP_NAME):
""" add users to moderator group """
try:
- group = Group.objects.get(name=group_name)
+ Group.objects.get(name=group_name)
except Group.DoesNotExist:
raise Http404('The Group {0} does not exist.'.format(group_name))
for user in users:
@@ -95,12 +102,19 @@ def get_html_text(md_text):
return Markdown().convert(md_text)
+def formfield_callback(field):
+ if (isinstance(field, models.TextField) and field.name == 'expected_output'
+ or field.name == 'expected_input'):
+ return fields.CharField(strip=False)
+ return field.formfield()
+
+
@email_verified
def index(request, next_url=None):
"""The start page.
"""
user = request.user
- if user.is_authenticated():
+ if user.is_authenticated:
if is_moderator(user):
return my_redirect('/exam/manage/' if not next_url else next_url)
return my_redirect("/exam/quizzes/" if not next_url else next_url)
@@ -113,7 +127,7 @@ def user_register(request):
Create a user and corresponding profile and store roll_number also."""
user = request.user
- if user.is_authenticated():
+ if user.is_authenticated:
return my_redirect("/exam/quizzes/")
context = {}
if request.method == "POST":
@@ -154,27 +168,41 @@ def user_logout(request):
def quizlist_user(request, enrolled=None, msg=None):
"""Show All Quizzes that is available to logged-in user."""
user = request.user
+ courses_data = []
if request.method == "POST":
course_code = request.POST.get('course_code')
hidden_courses = Course.objects.get_hidden_courses(code=course_code)
- courses = hidden_courses if hidden_courses else None
- title = 'Search'
-
- elif enrolled is not None:
- courses = user.students.all()
- title = 'Enrolled Courses'
+ courses = hidden_courses
+ title = 'Search Results'
else:
- courses = Course.objects.filter(
- active=True, is_trial=False
+ courses = list(Course.objects.filter(
+ active=True, is_trial=False,
).exclude(
~Q(requests=user), ~Q(rejected=user), hidden=True
+ ).order_by('-id'))
+ enrolled_course = list(
+ user.students.filter(is_trial=False).order_by('-id')
)
+ courses.extend(enrolled_course)
title = 'All Courses'
+ for course in courses:
+ if course.students.filter(id=user.id).exists():
+ _percent = course.get_completion_percent(user)
+ else:
+ _percent = None
+ courses_data.append(
+ {
+ 'data': course,
+ 'completion_percentage': _percent,
+ }
+ )
+
+ messages.info(request, msg)
context = {
- 'user': user, 'courses': courses,
- 'title': title, 'msg': msg
+ 'user': user, 'courses': courses_data,
+ 'title': title
}
return my_render_to_response(request, "yaksh/quizzes_user.html", context)
@@ -196,28 +224,27 @@ def add_question(request, question_id=None):
user = request.user
test_case_type = None
- if question_id is None:
- question = Question(user=user)
- question.save()
- else:
+ if question_id is not None:
question = Question.objects.get(id=question_id)
-
- if request.method == "POST" and 'delete_files' in request.POST:
- remove_files_id = request.POST.getlist('clear')
- if remove_files_id:
- files = FileUpload.objects.filter(id__in=remove_files_id)
- for file in files:
- file.remove()
+ uploaded_files = FileUpload.objects.filter(question_id=question.id)
+ else:
+ question = None
+ uploaded_files = []
if request.method == 'POST':
qform = QuestionForm(request.POST, instance=question)
fileform = FileForm(request.POST, request.FILES)
+ remove_files_id = request.POST.getlist('clear')
files = request.FILES.getlist('file_field')
extract_files_id = request.POST.getlist('extract')
hide_files_id = request.POST.getlist('hide')
if files:
for file in files:
FileUpload.objects.get_or_create(question=question, file=file)
+ if remove_files_id:
+ files = FileUpload.objects.filter(id__in=remove_files_id)
+ for file in files:
+ file.remove()
if extract_files_id:
files = FileUpload.objects.filter(id__in=extract_files_id)
for file in files:
@@ -228,14 +255,17 @@ def add_question(request, question_id=None):
file.toggle_hide_status()
formsets = []
for testcase in TestCase.__subclasses__():
- formset = inlineformset_factory(Question, testcase, extra=0,
- fields='__all__')
+ formset = inlineformset_factory(
+ Question, testcase, extra=0,
+ fields='__all__',
+ form=TestcaseForm,
+ formfield_callback=formfield_callback
+ )
formsets.append(formset(
request.POST, request.FILES, instance=question
)
)
files = request.FILES.getlist('file_field')
- uploaded_files = FileUpload.objects.filter(question_id=question.id)
if qform.is_valid():
question = qform.save(commit=False)
question.user = user
@@ -246,6 +276,8 @@ def add_question(request, question_id=None):
if formset.is_valid():
formset.save()
test_case_type = request.POST.get('case_type', None)
+ uploaded_files = FileUpload.objects.filter(question_id=question.id)
+ messages.success(request, "Question saved successfully")
else:
context = {
'qform': qform,
@@ -254,22 +286,22 @@ def add_question(request, question_id=None):
'formsets': formsets,
'uploaded_files': uploaded_files
}
- return my_render_to_response(
- request, "yaksh/add_question.html", context
- )
+ messages.warning(request, "Unable to save the question")
+ return render(request, "yaksh/add_question.html", context)
qform = QuestionForm(instance=question)
fileform = FileForm()
- uploaded_files = FileUpload.objects.filter(question_id=question.id)
formsets = []
for testcase in TestCase.__subclasses__():
if test_case_type == testcase.__name__.lower():
formset = inlineformset_factory(
- Question, testcase, extra=1, fields='__all__'
+ Question, testcase, extra=1, fields='__all__',
+ form=TestcaseForm
)
else:
formset = inlineformset_factory(
- Question, testcase, extra=0, fields='__all__'
+ Question, testcase, extra=0, fields='__all__',
+ form=TestcaseForm
)
formsets.append(
formset(
@@ -279,9 +311,10 @@ def add_question(request, question_id=None):
)
context = {'qform': qform, 'fileform': fileform, 'question': question,
'formsets': formsets, 'uploaded_files': uploaded_files}
- return my_render_to_response(
- request, "yaksh/add_question.html", context
- )
+ if question is not None:
+ context["testcase_options"] = question.get_test_case_options()
+
+ return render(request, "yaksh/add_question.html", context)
@login_required
@@ -310,15 +343,11 @@ def add_quiz(request, quiz_id=None, course_id=None):
if quiz is None:
form.instance.creator = user
form.save()
- if not course_id:
- return my_redirect("/exam/manage/courses/all_quizzes/")
- else:
- return my_redirect("/exam/manage/courses/")
-
+ messages.success(request, "Quiz saved successfully")
else:
form = QuizForm(instance=quiz)
- context["course_id"] = course_id
- context["quiz"] = quiz
+ context["course_id"] = course_id
+ context["quiz"] = quiz
context["form"] = form
return my_render_to_response(request, 'yaksh/add_quiz.html', context)
@@ -355,16 +384,13 @@ def add_exercise(request, quiz_id=None, course_id=None):
quiz.duration = 1000
quiz.pass_criteria = 0
quiz.save()
-
- if not course_id:
- return my_redirect("/exam/manage/courses/all_quizzes/")
- else:
- return my_redirect("/exam/manage/courses/")
-
+ messages.success(
+ request, "{0} saved successfully".format(quiz.description)
+ )
else:
form = ExerciseForm(instance=quiz)
context["exercise"] = quiz
- context["course_id"] = course_id
+ context["course_id"] = course_id
context["form"] = form
return my_render_to_response(request, 'yaksh/add_exercise.html', context)
@@ -376,34 +402,18 @@ def prof_manage(request, msg=None):
"""Take credentials of the user with professor/moderator
rights/permissions and log in."""
user = request.user
- if not user.is_authenticated():
+ if not user.is_authenticated:
return my_redirect('/exam/login')
if not is_moderator(user):
return my_redirect('/exam/')
- courses = Course.objects.filter(Q(creator=user) | Q(teachers=user),
- is_trial=False)
- trial_paper = AnswerPaper.objects.filter(
- user=user, question_paper__quiz__is_trial=True,
- course__is_trial=True
- )
- if request.method == "POST":
- delete_paper = request.POST.getlist('delete_paper')
- for answerpaper_id in delete_paper:
- answerpaper = AnswerPaper.objects.get(id=answerpaper_id)
- qpaper = answerpaper.question_paper
- answerpaper.course.remove_trial_modules()
- answerpaper.course.delete()
- if qpaper.quiz.is_trial:
- qpaper.quiz.delete()
- else:
- if qpaper.answerpaper_set.count() == 1:
- qpaper.quiz.delete()
- else:
- answerpaper.delete()
-
- context = {'user': user, 'courses': courses,
- 'trial_paper': trial_paper, 'msg': msg
- }
+ courses = Course.objects.get_queryset().filter(
+ Q(creator=user) | Q(teachers=user),
+ is_trial=False).distinct().order_by("-active")
+ paginator = Paginator(courses, 20)
+ page = request.GET.get('page')
+ courses = paginator.get_page(page)
+ messages.info(request, msg)
+ context = {'user': user, 'objects': courses}
return my_render_to_response(
request, 'yaksh/moderator_dashboard.html', context
)
@@ -414,7 +424,7 @@ def user_login(request):
user = request.user
context = {}
- if user.is_authenticated():
+ if user.is_authenticated:
return index(request)
next_url = request.GET.get('next')
@@ -469,22 +479,30 @@ def start(request, questionpaper_id=None, attempt_num=None, course_id=None,
# unit module prerequiste check
if learning_module.has_prerequisite():
- if not learning_module.is_prerequisite_passed(user, course):
+ if not learning_module.is_prerequisite_complete(user, course):
msg = "You have not completed the module previous to {0}".format(
learning_module.name)
return course_modules(request, course_id, msg)
+ if learning_module.check_prerequisite_passes:
+ if not learning_module.is_prerequisite_passed(user, course):
+ msg = (
+ "You have not successfully passed the module"
+ " previous to {0}".format(learning_module.name)
+ )
+ return course_modules(request, course_id, msg)
+
# is user enrolled in the course
if not course.is_enrolled(user):
msg = 'You are not enrolled in {0} course'.format(course.name)
- if is_moderator(user):
+ if is_moderator(user) and course.is_trial:
return prof_manage(request, msg=msg)
return quizlist_user(request, msg=msg)
# if course is active and is not expired
if not course.active or not course.is_active_enrollment():
msg = "{0} is either expired or not active".format(course.name)
- if is_moderator(user):
+ if is_moderator(user) and course.is_trial:
return prof_manage(request, msg=msg)
return quizlist_user(request, msg=msg)
@@ -492,17 +510,17 @@ def start(request, questionpaper_id=None, attempt_num=None, course_id=None,
if quest_paper.quiz.is_expired() or not quest_paper.quiz.active:
msg = "{0} is either expired or not active".format(
quest_paper.quiz.description)
- if is_moderator(user):
+ if is_moderator(user) and course.is_trial:
return prof_manage(request, msg=msg)
return view_module(request, module_id=module_id, course_id=course_id,
msg=msg)
# prerequisite check and passing criteria for quiz
if learning_unit.has_prerequisite():
- if not learning_unit.is_prerequisite_passed(
+ if not learning_unit.is_prerequisite_complete(
user, learning_module, course):
msg = "You have not completed the previous Lesson/Quiz/Exercise"
- if is_moderator(user):
+ if is_moderator(user) and course.is_trial:
return prof_manage(request, msg=msg)
return view_module(request, module_id=module_id,
course_id=course_id, msg=msg)
@@ -513,23 +531,28 @@ def start(request, questionpaper_id=None, attempt_num=None, course_id=None,
# if any previous attempt
last_attempt = AnswerPaper.objects.get_user_last_attempt(
quest_paper, user, course_id)
- if last_attempt and last_attempt.is_attempt_inprogress():
- return show_question(
- request, last_attempt.current_question(), last_attempt,
- course_id=course_id, module_id=module_id,
- previous_question=last_attempt.current_question()
- )
+
+ if last_attempt:
+ if last_attempt.is_attempt_inprogress():
+ return show_question(
+ request, last_attempt.current_question(), last_attempt,
+ course_id=course_id, module_id=module_id,
+ previous_question=last_attempt.current_question()
+ )
+ attempt_number = last_attempt.attempt_number + 1
+ else:
+ attempt_number = 1
+
# allowed to start
if not quest_paper.can_attempt_now(user, course_id)[0]:
msg = quest_paper.can_attempt_now(user, course_id)[1]
if is_moderator(user):
return prof_manage(request, msg=msg)
- return view_module(request, module_id=module_id, course_id=course_id,
- msg=msg)
- if not last_attempt:
- attempt_number = 1
- else:
- attempt_number = last_attempt.attempt_number + 1
+ return complete(
+ request, msg, last_attempt.attempt_number, quest_paper.id,
+ course_id=course_id, module_id=module_id
+ )
+
if attempt_num is None and not quest_paper.quiz.is_exercise:
context = {
'user': user,
@@ -627,7 +650,7 @@ def show_question(request, question, paper, error_message=None,
'can_skip': can_skip,
'delay_time': delay_time,
'quiz_type': quiz_type,
- 'all_modules': all_modules
+ 'all_modules': all_modules,
}
answers = paper.get_previous_answers(question)
if answers:
@@ -729,19 +752,17 @@ def check(request, q_id, attempt_num=None, questionpaper_id=None,
for fname in assignment_filename:
fname._name = fname._name.replace(" ", "_")
assignment_files = AssignmentUpload.objects.filter(
- assignmentQuestion=current_question,
- assignmentFile__icontains=fname, user=user,
- question_paper=questionpaper_id)
+ assignmentQuestion=current_question, course_id=course_id,
+ assignmentFile__icontains=fname, user=user,
+ question_paper=questionpaper_id)
if assignment_files.exists():
- assign_file = assignment_files.get(
- assignmentQuestion=current_question,
- assignmentFile__icontains=fname, user=user,
- question_paper=questionpaper_id)
+ assign_file = assignment_files.first()
if os.path.exists(assign_file.assignmentFile.path):
os.remove(assign_file.assignmentFile.path)
assign_file.delete()
AssignmentUpload.objects.create(
user=user, assignmentQuestion=current_question,
+ course_id=course_id,
assignmentFile=fname, question_paper_id=questionpaper_id
)
user_answer = 'ASSIGNMENT UPLOADED'
@@ -903,8 +924,9 @@ def complete(request, reason=None, attempt_num=None, questionpaper_id=None,
"""Show a page to inform user that the quiz has been completed."""
user = request.user
if questionpaper_id is None:
- message = reason or "An Unexpected Error occurred. Please contact your '\
- 'instructor/administrator.'"
+ message = reason or ("An Unexpected Error occurred. Please "
+ "contact your instructor/administrator."
+ )
context = {'message': message}
return my_render_to_response(request, 'yaksh/complete.html', context)
else:
@@ -942,19 +964,22 @@ def add_course(request, course_id=None):
if not is_moderator(user):
raise Http404('You are not allowed to view this page')
if request.method == 'POST':
- form = CourseForm(request.POST, instance=course)
+ form = CourseForm(user, request.POST, instance=course)
if form.is_valid():
new_course = form.save(commit=False)
if course_id is None:
new_course.creator = user
new_course.save()
+ messages.success(
+ request, "Saved {0} successfully".format(new_course.name)
+ )
return my_redirect('/exam/manage/courses')
else:
return my_render_to_response(
request, 'yaksh/add_course.html', {'form': form}
)
else:
- form = CourseForm(instance=course)
+ form = CourseForm(user, instance=course)
return my_render_to_response(
request, 'yaksh/add_course.html', {'form': form}
)
@@ -970,9 +995,15 @@ def enroll_request(request, course_id):
'Unable to add enrollments for this course, please contact your '
'instructor/administrator.'
)
- return complete(request, msg, attempt_num=None, questionpaper_id=None)
-
- course.request(user)
+ messages.warning(request, msg)
+ else:
+ course.request(user)
+ messages.success(
+ request,
+ "Enrollment request sent for {0} by {1}".format(
+ course.name, course.creator.get_full_name()
+ )
+ )
if is_moderator(user):
return my_redirect('/exam/manage/courses')
else:
@@ -987,6 +1018,12 @@ def self_enroll(request, course_id):
if course.is_self_enroll():
was_rejected = False
course.enroll(was_rejected, user)
+ messages.success(
+ request,
+ "Enrolled in {0} by {1}".format(
+ course.name, course.creator.get_full_name()
+ )
+ )
if is_moderator(user):
return my_redirect('/exam/manage/')
else:
@@ -1000,11 +1037,31 @@ def courses(request):
if not is_moderator(user):
raise Http404('You are not allowed to view this page')
courses = Course.objects.filter(
- creator=user, is_trial=False).order_by('-active', '-id')
- allotted_courses = Course.objects.filter(
- teachers=user, is_trial=False).order_by('-active', '-id')
- context = {'courses': courses, "allotted_courses": allotted_courses,
- "type": "courses"}
+ Q(creator=user) | Q(teachers=user),
+ is_trial=False).order_by('-active').distinct()
+
+ form = SearchFilterForm()
+
+ if request.method == 'POST':
+ course_tags = request.POST.get('search_tags')
+ course_status = request.POST.get('search_status')
+
+ if course_status == 'select' :
+ courses = courses.filter(
+ name__contains=course_tags)
+ elif course_status == 'active' :
+ courses = courses.filter(
+ name__contains=course_tags, active=True)
+ elif course_status == 'closed':
+ courses = courses.filter(
+ name__contains=course_tags, active=False)
+
+ paginator = Paginator(courses, 30)
+ page = request.GET.get('page')
+ courses = paginator.get_page(page)
+ courses_found = courses.object_list.count()
+ context = {'objects': courses, 'created': True,
+ 'form': form, 'courses_found': courses_found}
return my_render_to_response(request, 'yaksh/courses.html', context)
@@ -1039,7 +1096,8 @@ def enroll(request, course_id, user_id=None, was_rejected=False):
' please contact your '
'instructor/administrator.'
)
- return complete(request, msg, attempt_num=None, questionpaper_id=None)
+ messages.warning(request, msg)
+ return my_redirect(reverse('yaksh:course_students', args=[course_id]))
if not course.is_creator(user) and not course.is_teacher(user):
raise Http404('This course does not belong to you')
@@ -1049,12 +1107,13 @@ def enroll(request, course_id, user_id=None, was_rejected=False):
else:
enroll_ids = [user_id]
if not enroll_ids:
- return my_render_to_response(
- request, 'yaksh/course_detail.html', {'course': course}
- )
+ messages.warning(request, "Please select atleast one student")
+ return my_redirect(reverse('yaksh:course_students', args=[course_id]))
+
users = User.objects.filter(id__in=enroll_ids)
course.enroll(was_rejected, *users)
- return course_detail(request, course_id)
+ messages.success(request, "Enrolled student(s) successfully")
+ return my_redirect(reverse('yaksh:course_students', args=[course_id]))
@login_required
@@ -1080,9 +1139,10 @@ def send_mail(request, course_id, user_id=None):
message = send_bulk_mail(
subject, email_body, recipients, attachments
)
+ messages.info(request, message)
context = {
'course': course, 'message': message,
- 'state': 'mail'
+ 'enrolled': course.get_enrolled(), 'is_mail': True
}
return my_render_to_response(request, 'yaksh/course_detail.html', context)
@@ -1103,14 +1163,13 @@ def reject(request, course_id, user_id=None, was_enrolled=False):
else:
reject_ids = [user_id]
if not reject_ids:
- message = "Please select atleast one User"
- return my_render_to_response(
- request, 'yaksh/course_detail.html',
- {'course': course, 'message': message},
- )
+ messages.warning(request, "Please select atleast one student")
+ return my_redirect(reverse('yaksh:course_students', args=[course_id]))
+
users = User.objects.filter(id__in=reject_ids)
course.reject(was_enrolled, *users)
- return course_detail(request, course_id)
+ messages.success(request, "Rejected students successfully")
+ return my_redirect(reverse('yaksh:course_students', args=[course_id]))
@login_required
@@ -1126,9 +1185,12 @@ def toggle_course_status(request, course_id):
if course.active:
course.deactivate()
+ message = '{0} deactivated successfully'.format(course.name)
else:
course.activate()
+ message = '{0} activated successfully'.format(course.name)
course.save()
+ messages.info(request, message)
return my_redirect("/exam/manage/courses")
@@ -1173,17 +1235,19 @@ def monitor(request, quiz_id=None, course_id=None):
"""Monitor the progress of the papers taken so far."""
user = request.user
- if not user.is_authenticated() or not is_moderator(user):
+ if not is_moderator(user):
raise Http404('You are not allowed to view this page!')
if quiz_id is None:
- course_details = Course.objects.filter(
+ courses = Course.objects.filter(
Q(creator=user) | Q(teachers=user),
is_trial=False
- ).distinct()
+ ).order_by("-active").distinct()
+ paginator = Paginator(courses, 30)
+ page = request.GET.get('page')
+ courses = paginator.get_page(page)
context = {
- "papers": [], "course_details": course_details,
- "msg": "Monitor"
+ "papers": [], "objects": courses, "msg": "Monitor"
}
return my_render_to_response(request, 'yaksh/monitor.html', context)
# quiz_id is not None.
@@ -1206,9 +1270,10 @@ def monitor(request, quiz_id=None, course_id=None):
else:
attempt_numbers = []
latest_attempts = []
- papers = AnswerPaper.objects.filter(question_paper=q_paper,
- course_id=course_id).order_by(
- 'user__profile__roll_number'
+ papers = AnswerPaper.objects.filter(
+ question_paper_id=q_paper.first().id,
+ course_id=course_id).order_by(
+ 'user__profile__roll_number'
)
users = papers.values_list('user').distinct()
for auser in users:
@@ -1251,10 +1316,16 @@ def ajax_questions_filter(request):
if language:
filter_dict['language'] = str(language)
- questions = Question.objects.filter(**filter_dict)
-
+ questions = Question.objects.get_queryset().filter(
+ **filter_dict).order_by('id')
+ paginator = Paginator(questions, 30)
+ page = request.GET.get('page')
+ questions = paginator.get_page(page)
return my_render_to_response(
- request, 'yaksh/ajax_question_filter.html', {'questions': questions}
+ request, 'yaksh/ajax_question_filter.html', {
+ 'questions': questions,
+ 'objects': questions
+ }
)
@@ -1284,12 +1355,12 @@ def _remove_already_present(questionpaper_id, questions):
return questions
-def _get_questions_from_tags(question_tags, user):
+def _get_questions_from_tags(question_tags, user, active=True):
search_tags = []
for tags in question_tags:
search_tags.extend(re.split('[; |, |\*|\n]', tags))
return Question.objects.filter(tags__name__in=search_tags,
- user=user).distinct()
+ user=user, active=active).distinct()
@login_required
@@ -1347,19 +1418,27 @@ def design_questionpaper(request, quiz_id, questionpaper_id=None,
question_paper.fixed_question_order = questions_order
question_paper.save()
question_paper.fixed_questions.add(*questions)
+ messages.success(request, "Questions added successfully")
+ else:
+ messages.warning(request, "Please select atleast one question")
if 'remove-fixed' in request.POST:
question_ids = request.POST.getlist('added-questions', None)
- if question_paper.fixed_question_order:
- que_order = question_paper.fixed_question_order.split(",")
- for qid in question_ids:
- que_order.remove(qid)
- if que_order:
- question_paper.fixed_question_order = ",".join(que_order)
- else:
- question_paper.fixed_question_order = ""
- question_paper.save()
- question_paper.fixed_questions.remove(*question_ids)
+ if question_ids:
+ if question_paper.fixed_question_order:
+ que_order = question_paper.fixed_question_order.split(",")
+ for qid in question_ids:
+ que_order.remove(qid)
+ if que_order:
+ question_paper.fixed_question_order = ",".join(
+ que_order)
+ else:
+ question_paper.fixed_question_order = ""
+ question_paper.save()
+ question_paper.fixed_questions.remove(*question_ids)
+ messages.success(request, "Questions removed successfully")
+ else:
+ messages.warning(request, "Please select atleast one question")
if 'add-random' in request.POST:
question_ids = request.POST.getlist('random_questions', None)
@@ -1371,14 +1450,21 @@ def design_questionpaper(request, quiz_id, questionpaper_id=None,
random_ques = Question.objects.filter(id__in=question_ids)
random_set.questions.add(*random_ques)
question_paper.random_questions.add(random_set)
+ messages.success(request, "Questions removed successfully")
+ else:
+ messages.warning(request, "Please select atleast one question")
if 'remove-random' in request.POST:
random_set_ids = request.POST.getlist('random_sets', None)
- question_paper.random_questions.remove(*random_set_ids)
+ if random_set_ids:
+ question_paper.random_questions.remove(*random_set_ids)
+ messages.success(request, "Questions removed successfully")
+ else:
+ messages.warning(request, "Please select question set")
if 'save' in request.POST or 'back' in request.POST:
qpaper_form.save()
- return my_redirect('/exam/manage/courses/all_quizzes/')
+ messages.success(request, "Question Paper saved successfully")
if marks:
questions = _get_questions(user, question_type, marks)
@@ -1416,15 +1502,21 @@ def show_all_questions(request):
user = request.user
context = {}
+ message = None
if not is_moderator(user):
raise Http404("You are not allowed to view this page !")
- questions = Question.objects.filter(user_id=user.id, active=True)
+ questions = Question.objects.get_queryset().filter(
+ user_id=user.id, active=True).order_by('id')
form = QuestionFilterForm(user=user)
user_tags = questions.values_list('tags', flat=True).distinct()
all_tags = Tag.objects.filter(id__in=user_tags)
upload_form = UploadFileForm()
+ paginator = Paginator(questions, 30)
+ page = request.GET.get('page')
+ questions = paginator.get_page(page)
context['questions'] = questions
+ context['objects'] = questions
context['all_tags'] = all_tags
context['papers'] = []
context['question'] = None
@@ -1440,6 +1532,7 @@ def show_all_questions(request):
for question in questions:
question.active = False
question.save()
+ message = "Questions deleted successfully"
if request.POST.get('upload') == 'upload':
form = UploadFileForm(request.POST, request.FILES)
@@ -1449,14 +1542,12 @@ def show_all_questions(request):
ques = Question()
if file_extension == "zip":
files, extract_path = extract_files(questions_file)
- context['message'] = ques.read_yaml(extract_path, user,
- files)
+ message = ques.read_yaml(extract_path, user, files)
elif file_extension in ["yaml", "yml"]:
questions = questions_file.read()
- context['message'] = ques.load_questions(questions, user)
+ message = ques.load_questions(questions, user)
else:
message = "Please Upload a ZIP file"
- context['message'] = message
if request.POST.get('download') == 'download':
question_ids = request.POST.getlist('question')
@@ -1471,8 +1562,7 @@ def show_all_questions(request):
response.write(zip_file.read())
return response
else:
- context['msg'] = ("Please select atleast" +
- "one question to download")
+ message = "Please select atleast one question to download"
if request.POST.get('test') == 'test':
question_ids = request.POST.getlist("question")
@@ -1484,13 +1574,13 @@ def show_all_questions(request):
return my_redirect("/exam/start/1/{0}/{1}/{2}".format(
trial_module.id, trial_paper.id, trial_course.id))
else:
- context["msg"] = "Please select atleast one question to test"
+ message = "Please select atleast one question to test"
if request.POST.get('question_tags'):
question_tags = request.POST.getlist("question_tags")
search_result = _get_questions_from_tags(question_tags, user)
context['questions'] = search_result
-
+ messages.info(request, message)
return my_render_to_response(request, 'yaksh/showquestions.html', context)
@@ -1499,7 +1589,7 @@ def show_all_questions(request):
def user_data(request, user_id, questionpaper_id=None, course_id=None):
"""Render user data."""
current_user = request.user
- if not current_user.is_authenticated() or not is_moderator(current_user):
+ if not is_moderator(current_user):
raise Http404('You are not allowed to view this page!')
user = User.objects.get(id=user_id)
data = AnswerPaper.objects.get_user_data(user, questionpaper_id, course_id)
@@ -1602,12 +1692,17 @@ def grade_user(request, quiz_id=None, user_id=None, attempt_number=None,
and update all their marks and also give comments for each paper.
"""
current_user = request.user
- if not current_user.is_authenticated() or not is_moderator(current_user):
+ if not is_moderator(current_user):
raise Http404('You are not allowed to view this page!')
- course_details = Course.objects.filter(Q(creator=current_user) |
- Q(teachers=current_user),
- is_trial=False).distinct()
- context = {"course_details": course_details}
+ if not course_id:
+ courses = Course.objects.filter(
+ Q(creator=current_user) | Q(teachers=current_user), is_trial=False
+ ).order_by("-active").distinct()
+ paginator = Paginator(courses, 30)
+ page = request.GET.get('page')
+ courses = paginator.get_page(page)
+ context = {"objects": courses, "msg": "grade"}
+
if quiz_id is not None:
questionpaper_id = QuestionPaper.objects.filter(
quiz_id=quiz_id
@@ -1620,16 +1715,16 @@ def grade_user(request, quiz_id=None, user_id=None, attempt_number=None,
if not course.is_creator(current_user) and not \
course.is_teacher(current_user):
raise Http404('This course does not belong to you')
-
has_quiz_assignments = AssignmentUpload.objects.filter(
- question_paper_id=questionpaper_id
+ question_paper_id__in=questionpaper_id
).exists()
context = {
"users": user_details,
"quiz_id": quiz_id,
"quiz": quiz,
"has_quiz_assignments": has_quiz_assignments,
- "course_id": course_id
+ "course_id": course_id,
+ "status": "grade"
}
if user_id is not None:
attempts = AnswerPaper.objects.get_user_all_attempts(
@@ -1641,7 +1736,7 @@ def grade_user(request, quiz_id=None, user_id=None, attempt_number=None,
except IndexError:
raise Http404('No attempts for paper')
has_user_assignments = AssignmentUpload.objects.filter(
- question_paper_id=questionpaper_id,
+ question_paper_id__in=questionpaper_id,
user_id=user_id
).exists()
user = User.objects.get(id=user_id)
@@ -1656,13 +1751,13 @@ def grade_user(request, quiz_id=None, user_id=None, attempt_number=None,
"user_id": user_id,
"has_user_assignments": has_user_assignments,
"has_quiz_assignments": has_quiz_assignments,
- "course_id": course_id
+ "course_id": course_id,
+ "status": "grade"
}
if request.method == "POST":
papers = data['papers']
for paper in papers:
- for question, answers in six.iteritems(
- paper.get_question_answers()):
+ for question, answers in paper.get_question_answers().items():
marks = float(request.POST.get('q%d_marks' % question.id, 0))
answer = answers[-1]['answer']
answer.set_marks(marks)
@@ -1671,8 +1766,10 @@ def grade_user(request, quiz_id=None, user_id=None, attempt_number=None,
paper.comments = request.POST.get(
'comments_%d' % paper.question_paper.id, 'No comments')
paper.save()
+ messages.success(request, "Student data saved successfully")
- course_status = CourseStatus.objects.filter(course=course, user=user)
+ course_status = CourseStatus.objects.filter(
+ course_id=course.id, user_id=user.id)
if course_status.exists():
course_status.first().set_grade()
@@ -1763,7 +1860,8 @@ def search_teacher(request, course_id):
)
context['success'] = True
context['teachers'] = teachers
- return my_render_to_response(request, 'yaksh/addteacher.html', context)
+ context['is_add_teacher'] = True
+ return my_render_to_response(request, 'yaksh/course_detail.html', context)
@login_required
@@ -1813,7 +1911,9 @@ def add_teacher(request, course_id):
course.add_teachers(*teachers)
context['status'] = True
context['teachers_added'] = teachers
- return my_render_to_response(request, 'yaksh/addteacher.html', context)
+ messages.success(request, "Added teachers successfully")
+ context['is_add_teacher'] = True
+ return my_render_to_response(request, 'yaksh/course_detail.html', context)
@login_required
@@ -1829,9 +1929,13 @@ def remove_teachers(request, course_id):
if request.method == "POST":
teacher_ids = request.POST.getlist('remove')
- teachers = User.objects.filter(id__in=teacher_ids)
- course.remove_teachers(*teachers)
- return my_redirect('/exam/manage/courses')
+ if teacher_ids:
+ teachers = User.objects.filter(id__in=teacher_ids)
+ course.remove_teachers(*teachers)
+ messages.success(request, "Removed teachers successfully")
+ else:
+ messages.warning(request, "Please select atleast one teacher")
+ return course_teachers(request, course_id)
def test_mode(user, godmode=False, questions_list=None, quiz_id=None,
@@ -1872,6 +1976,10 @@ def test_quiz(request, mode, quiz_id, course_id=None):
current_user = request.user
quiz = Quiz.objects.get(id=quiz_id)
if (quiz.is_expired() or not quiz.active) and not godmode:
+ messages.warning(
+ request,
+ "{0} is either expired or inactive".format(quiz.description)
+ )
return my_redirect('/exam/manage')
trial_questionpaper, trial_course, trial_module = test_mode(
@@ -1890,10 +1998,10 @@ def view_answerpaper(request, questionpaper_id, course_id):
data = AnswerPaper.objects.get_user_data(user, questionpaper_id,
course_id)
has_user_assignment = AssignmentUpload.objects.filter(
- user=user,
+ user=user, course_id=course.id,
question_paper_id=questionpaper_id
).exists()
- context = {'data': data, 'quiz': quiz,
+ context = {'data': data, 'quiz': quiz, 'course_id': course.id,
"has_user_assignment": has_user_assignment}
return my_render_to_response(
request, 'yaksh/view_answerpaper.html', context
@@ -2048,7 +2156,7 @@ def new_activation(request, email=None):
try:
user = User.objects.get(email=email)
except MultipleObjectsReturned:
- context['email_err_msg'] = "Multiple entries found for this email"\
+ context['email_err_msg'] = "Multiple entries found for this email "\
"Please change your email"
return my_render_to_response(
request, 'yaksh/activation_status.html', context
@@ -2100,13 +2208,18 @@ def update_email(request):
@login_required
@email_verified
-def download_assignment_file(request, quiz_id, question_id=None, user_id=None):
+def download_assignment_file(request, quiz_id, course_id,
+ question_id=None, user_id=None):
user = request.user
- if not is_moderator(user):
- raise Http404("You are not allowed to view this page")
- qp = QuestionPaper.objects.get(quiz_id=quiz_id)
+ course = get_object_or_404(Course, pk=course_id)
+ if (not course.is_creator(user) and not course.is_teacher(user) and
+ not course.is_student(user)):
+ raise Http404("You are not allowed to download files for {0}".format(
+ course.name)
+ )
+ qp = get_object_or_404(QuestionPaper, quiz_id=quiz_id)
assignment_files, file_name = AssignmentUpload.objects.get_assignments(
- qp, question_id, user_id
+ qp, question_id, user_id, course_id
)
zipfile_name = string_io()
zip_file = zipfile.ZipFile(zipfile_name, "w")
@@ -2137,72 +2250,64 @@ def upload_users(request, course_id):
context = {'course': course}
if not (course.is_teacher(user) or course.is_creator(user)):
- msg = 'You do not have permissions to this course.'
- return complete(request, reason=msg)
+ raise Http404('You are not allowed to view this page!')
if request.method == 'POST':
if 'csv_file' not in request.FILES:
- context['message'] = "Please upload a CSV file."
- return my_render_to_response(
- request, 'yaksh/course_detail.html', context
- )
+ messages.warning(request, "Please upload a CSV file.")
+ return my_redirect(reverse('yaksh:course_students',
+ args=[course_id]))
csv_file = request.FILES['csv_file']
is_csv_file, dialect = is_csv(csv_file)
if not is_csv_file:
- context['message'] = "The file uploaded is not a CSV file."
- return my_render_to_response(
- request, 'yaksh/course_detail.html', context
- )
+ messages.warning(request, "The file uploaded is not a CSV file.")
+ return my_redirect(reverse('yaksh:course_students',
+ args=[course_id]))
required_fields = ['firstname', 'lastname', 'email']
try:
reader = csv.DictReader(
csv_file.read().decode('utf-8').splitlines(),
dialect=dialect)
except TypeError:
- context['message'] = "Bad CSV file"
- return my_render_to_response(
- request, 'yaksh/course_detail.html', context
- )
+ messages.warning(request, "Bad CSV file")
+ return my_redirect(reverse('yaksh:course_students',
+ args=[course_id]))
stripped_fieldnames = [
field.strip().lower() for field in reader.fieldnames]
for field in required_fields:
if field not in stripped_fieldnames:
- context['message'] = "The CSV file does not contain the"\
- " required headers"
- return my_render_to_response(
- request, 'yaksh/course_detail.html', context
- )
+ msg = "The CSV file does not contain the required headers"
+ messages.warning(request, msg)
+ return my_redirect(reverse('yaksh:course_students',
+ args=[course_id]))
reader.fieldnames = stripped_fieldnames
- context['upload_details'] = _read_user_csv(reader, course)
- return my_render_to_response(request, 'yaksh/course_detail.html', context)
+ _read_user_csv(request, reader, course)
+ return my_redirect(reverse('yaksh:course_students', args=[course_id]))
-def _read_user_csv(reader, course):
+def _read_user_csv(request, reader, course):
fields = reader.fieldnames
- upload_details = ["Upload Summary:"]
counter = 0
for row in reader:
counter += 1
(username, email, first_name, last_name, password, roll_no, institute,
department, remove) = _get_csv_values(row, fields)
if not email or not first_name or not last_name:
- upload_details.append("{0} -- Missing Values".format(counter))
+ messages.info(request, "{0} -- Missing Values".format(counter))
continue
users = User.objects.filter(username=username)
if users.exists():
user = users[0]
if remove.strip().lower() == 'true':
- if _remove_from_course(user, course):
- upload_details.append("{0} -- {1} -- User rejected".format(
- counter, user.username))
- continue
+ _remove_from_course(user, course)
+ messages.info(request, "{0} -- {1} -- User rejected".format(
+ counter, user.username))
else:
- if _add_to_course(user, course):
- upload_details.append("{0} -- {1} -- User rejected".format(
- counter, user.username))
- if user not in course.get_enrolled():
- upload_details.append("{0} -- {1} not added to course".format(
- counter, user))
- continue
+ _add_to_course(user, course)
+ messages.info(
+ request,
+ "{0} -- {1} -- User Added Successfully".format(
+ counter, user.username))
+ continue
user_defaults = {'email': email, 'first_name': first_name,
'last_name': last_name}
user, created = _create_or_update_user(username, password,
@@ -2216,11 +2321,10 @@ def _read_user_csv(reader, course):
course.students.add(user)
else:
state = "Updated"
- upload_details.append("{0} -- {1} -- User {2} Successfully".format(
- counter, user.username, state))
+ messages.info(request, "{0} -- {1} -- User {2} Successfully".format(
+ counter, user.username, state))
if counter == 0:
- upload_details.append("No rows in the CSV file")
- return upload_details
+ messages.warning(request, "No rows in the CSV file")
def _get_csv_values(row, fields):
@@ -2252,13 +2356,15 @@ def _get_csv_values(row, fields):
def _remove_from_course(user, course):
if user in course.get_enrolled():
course.reject(True, user)
- return True
+ else:
+ course.rejected.add(user)
def _add_to_course(user, course):
if user in course.get_rejected():
course.enroll(True, user)
- return True
+ else:
+ course.students.add(user)
def _create_or_update_user(username, password, defaults):
@@ -2300,15 +2406,22 @@ def duplicate_course(request, course_id):
if course.is_teacher(user) or course.is_creator(user):
# Create new entries of modules, lessons/quizzes
# from current course to copied course
- course.create_duplicate_course(user)
+ duplicate_course = course.create_duplicate_course(user)
+ msg = dedent(
+ '''\
+ Course duplication successful with the name {0}'''.format(
+ duplicate_course.name
+ )
+ )
+ messages.success(request, msg)
else:
msg = dedent(
'''\
You do not have permissions to clone {0} course, please contact
your instructor/administrator.'''.format(course.name)
)
- return complete(request, msg, attempt_num=None, questionpaper_id=None)
- return my_redirect('/exam/manage/courses/')
+ messages.warning(request, msg)
+ return my_redirect(reverse('yaksh:courses'))
@login_required
@@ -2345,9 +2458,9 @@ def edit_lesson(request, lesson_id=None, course_id=None):
course = get_object_or_404(Course, id=course_id)
if not course.is_creator(user) and not course.is_teacher(user):
raise Http404('This Lesson does not belong to you')
- redirect_url = "/exam/manage/courses/"
+ redirect_url = reverse("yaksh:get_course_modules", args=[course_id])
else:
- redirect_url = "/exam/manage/courses/all_lessons/"
+ redirect_url = reverse("yaksh:show_all_lessons")
context = {}
if request.method == "POST":
if "Save" in request.POST:
@@ -2372,7 +2485,9 @@ def edit_lesson(request, lesson_id=None, course_id=None):
LessonFile.objects.get_or_create(
lesson=lesson, file=les_file
)
- return my_redirect(redirect_url)
+ messages.success(
+ request, "Saved {0} successfully".format(lesson.name)
+ )
else:
context['lesson_form'] = lesson_form
context['error'] = lesson_form["video_file"].errors
@@ -2384,7 +2499,13 @@ def edit_lesson(request, lesson_id=None, course_id=None):
files = LessonFile.objects.filter(id__in=remove_files_id)
for file in files:
file.remove()
- return my_redirect(redirect_url)
+ messages.success(
+ request, "Deleted files successfully"
+ )
+ else:
+ messages.warning(
+ request, "Please select atleast one file to delete"
+ )
lesson_files = LessonFile.objects.filter(lesson=lesson)
lesson_files_form = LessonFileForm()
@@ -2417,17 +2538,24 @@ def show_lesson(request, lesson_id, module_id, course_id):
msg = "{0} is not active".format(learn_unit.lesson.name)
return view_module(request, module_id, course_id, msg)
if learn_module.has_prerequisite():
- if not learn_module.is_prerequisite_passed(user, course):
+ if not learn_module.is_prerequisite_complete(user, course):
msg = "You have not completed the module previous to {0}".format(
learn_module.name)
return view_module(request, module_id, course_id, msg)
+ if learn_module.check_prerequisite_passes:
+ if not learn_module.is_prerequisite_passed(user, course):
+ msg = (
+ "You have not successfully passed the module"
+ " previous to {0}".format(learn_module.name)
+ )
+ return view_module(request, module_id, course_id, msg)
# update course status with current unit
_update_unit_status(course_id, user, learn_unit)
all_modules = course.get_learning_modules()
if learn_unit.has_prerequisite():
- if not learn_unit.is_prerequisite_passed(user, learn_module, course):
+ if not learn_unit.is_prerequisite_complete(user, learn_module, course):
msg = "You have not completed previous Lesson/Quiz/Exercise"
return view_module(request, learn_module.id, course_id, msg=msg)
context = {'lesson': learn_unit.lesson, 'user': user,
@@ -2451,9 +2579,10 @@ def design_module(request, module_id, course_id=None):
learning_module = LearningModule.objects.get(id=module_id)
if request.method == "POST":
if "Add" in request.POST:
- add_values = request.POST.get("choosen_list").split(',')
+ add_values = request.POST.get("chosen_list")
to_add_list = []
if add_values:
+ add_values = add_values.split(',')
ordered_units = learning_module.get_learning_units()
if ordered_units.exists():
start_val = ordered_units.last().order + 1
@@ -2471,29 +2600,55 @@ def design_module(request, module_id, course_id=None):
type=type)
to_add_list.append(learning_unit)
learning_module.learning_unit.add(*to_add_list)
+ messages.success(request, "Lesson/Quiz added successfully")
+ else:
+ messages.warning(request, "Please select a lesson/quiz to add")
if "Change" in request.POST:
- order_list = request.POST.get("ordered_list").split(",")
- for order in order_list:
- learning_unit, learning_order = order.split(":")
- if learning_order:
- learning_unit = learning_module.learning_unit.get(
- id=learning_unit)
- learning_unit.order = learning_order
- learning_unit.save()
+ order_list = request.POST.get("ordered_list")
+ if order_list:
+ order_list = order_list.split(",")
+ for order in order_list:
+ learning_unit, learning_order = order.split(":")
+ if learning_order:
+ learning_unit = learning_module.learning_unit.get(
+ id=learning_unit)
+ learning_unit.order = learning_order
+ learning_unit.save()
+ messages.success(request, "Order changed successfully")
+ else:
+ messages.warning(
+ request, "Please select a lesson/quiz to change"
+ )
if "Remove" in request.POST:
remove_values = request.POST.getlist("delete_list")
if remove_values:
learning_module.learning_unit.remove(*remove_values)
LearningUnit.objects.filter(id__in=remove_values).delete()
+ messages.success(
+ request, "Lessons/quizzes deleted successfully"
+ )
+ else:
+ messages.warning(
+ request, "Please select a lesson/quiz to remove"
+ )
if "Change_prerequisite" in request.POST:
unit_list = request.POST.getlist("check_prereq")
- for unit in unit_list:
- learning_unit = learning_module.learning_unit.get(id=unit)
- learning_unit.toggle_check_prerequisite()
- learning_unit.save()
+ if unit_list:
+ for unit in unit_list:
+ learning_unit = learning_module.learning_unit.get(id=unit)
+ learning_unit.toggle_check_prerequisite()
+ learning_unit.save()
+ messages.success(
+ request, "Changed prerequisite status successfully"
+ )
+ else:
+ messages.warning(
+ request,
+ "Please select a lesson/quiz to change prerequisite"
+ )
added_quiz_lesson = learning_module.get_added_quiz_lesson()
quizzes = [("quiz", quiz) for quiz in Quiz.objects.filter(
@@ -2515,12 +2670,12 @@ def add_module(request, module_id=None, course_id=None):
user = request.user
if not is_moderator(user):
raise Http404('You are not allowed to view this page!')
- redirect_url = "/exam/manage/courses/all_learning_module/"
+ redirect_url = reverse("yaksh:show_all_modules")
if course_id:
course = Course.objects.get(id=course_id)
if not course.is_creator(user) and not course.is_teacher(user):
raise Http404('This course does not belong to you')
- redirect_url = "/exam/manage/courses/"
+ redirect_url = reverse("yaksh:get_course_modules", args=[course_id])
if module_id:
module = LearningModule.objects.get(id=module_id)
if not module.creator == user and not course_id:
@@ -2537,7 +2692,10 @@ def add_module(request, module_id=None, course_id=None):
module = module_form.save()
module.html_data = get_html_text(module.description)
module.save()
- return my_redirect(redirect_url)
+ messages.success(
+ request,
+ "Saved {0} successfully".format(module.name)
+ )
else:
context['module_form'] = module_form
@@ -2555,8 +2713,27 @@ def show_all_quizzes(request):
if not is_moderator(user):
raise Http404('You are not allowed to view this page!')
quizzes = Quiz.objects.filter(creator=user, is_trial=False)
- context = {"quizzes": quizzes, "type": "quiz"}
- return my_render_to_response(request, 'yaksh/courses.html', context)
+
+ form = SearchFilterForm()
+
+ if request.method == 'POST':
+ quiz_tags = request.POST.get('search_tags')
+ quiz_status = request.POST.get('search_status')
+
+ if quiz_status == 'select' :
+ quizzes = quizzes.filter(
+ description__contains=quiz_tags)
+ elif quiz_status == 'active' :
+ quizzes = quizzes.filter(
+ description__contains=quiz_tags, active=True)
+ elif quiz_status == 'closed':
+ quizzes = quizzes.filter(
+ description__contains=quiz_tags, active=False)
+ quizzes_found = quizzes.count()
+
+ context = {"quizzes": quizzes, "form": form,
+ "quizzes_found": quizzes_found}
+ return my_render_to_response(request, 'yaksh/quizzes.html', context)
@login_required
@@ -2566,8 +2743,27 @@ def show_all_lessons(request):
if not is_moderator(user):
raise Http404('You are not allowed to view this page!')
lessons = Lesson.objects.filter(creator=user)
- context = {"lessons": lessons, "type": "lesson"}
- return my_render_to_response(request, 'yaksh/courses.html', context)
+
+ form = SearchFilterForm()
+
+ if request.method == 'POST':
+ lesson_tags = request.POST.get('search_tags')
+ lesson_status = request.POST.get('search_status')
+
+ if lesson_status == 'select' :
+ lessons = lessons.filter(
+ description__contains=lesson_tags)
+ elif lesson_status == 'active' :
+ lessons = lessons.filter(
+ description__contains=lesson_tags, active=True)
+ elif lesson_status == 'closed':
+ lessons = lessons.filter(
+ description__contains=lesson_tags, active=False)
+ lessons_found = lessons.count()
+
+ context = {"lessons": lessons, "form": form,
+ "lessons_found": lessons_found}
+ return my_render_to_response(request, 'yaksh/lessons.html', context)
@login_required
@@ -2578,8 +2774,29 @@ def show_all_modules(request):
raise Http404('You are not allowed to view this page!')
learning_modules = LearningModule.objects.filter(
creator=user, is_trial=False)
- context = {"learning_modules": learning_modules, "type": "learning_module"}
- return my_render_to_response(request, 'yaksh/courses.html', context)
+
+ form = SearchFilterForm()
+
+ if request.method == 'POST':
+ module_tags = request.POST.get('search_tags')
+ module_status = request.POST.get('search_status')
+
+ if module_status == 'select' :
+ learning_modules = learning_modules.filter(
+ name__contains=module_tags)
+ elif module_status == 'active' :
+ learning_modules = learning_modules.filter(
+ name__contains=module_tags, active=True)
+ elif module_status == 'closed':
+ learning_modules = learning_modules.filter(
+ name__contains=module_tags, active=False)
+ learning_modules_found = learning_modules.count()
+
+ context = {"modules": learning_modules, "form": form,
+ "modules_found": learning_modules_found}
+ return my_render_to_response(
+ request, 'yaksh/modules.html', context
+ )
@login_required
@@ -2602,7 +2819,7 @@ def get_next_unit(request, course_id, module_id, current_unit_id=None,
user = request.user
course = Course.objects.prefetch_related("learning_module").get(
id=course_id)
- if user not in course.students.all():
+ if not course.students.filter(id=user.id).exists():
raise Http404('You are not enrolled for this course!')
learning_module = course.learning_module.prefetch_related(
"learning_unit").get(id=module_id)
@@ -2673,28 +2890,58 @@ def design_course(request, course_id):
learning_module.save()
to_add_list.append(learning_module)
course.learning_module.add(*to_add_list)
+ messages.success(request, "Modules added successfully")
+ else:
+ messages.warning(request, "Please select atleast one module")
if "Change" in request.POST:
- order_list = request.POST.get("ordered_list").split(",")
- for order in order_list:
- learning_unit, learning_order = order.split(":")
- if learning_order:
- learning_module = course.learning_module.get(
- id=learning_unit)
- learning_module.order = learning_order
- learning_module.save()
+ order_list = request.POST.get("ordered_list")
+ if order_list:
+ order_list = order_list.split(",")
+ for order in order_list:
+ learning_unit, learning_order = order.split(":")
+ if learning_order:
+ learning_module = course.learning_module.get(
+ id=learning_unit)
+ learning_module.order = learning_order
+ learning_module.save()
+ messages.success(request, "Changed order successfully")
+ else:
+ messages.warning(request, "Please select atleast one module")
if "Remove" in request.POST:
remove_values = request.POST.getlist("delete_list")
if remove_values:
course.learning_module.remove(*remove_values)
+ messages.success(request, "Modules removed successfully")
+ else:
+ messages.warning(request, "Please select atleast one module")
- if "Change_prerequisite" in request.POST:
+ if "change_prerequisite_completion" in request.POST:
unit_list = request.POST.getlist("check_prereq")
- for unit in unit_list:
- learning_module = course.learning_module.get(id=unit)
- learning_module.toggle_check_prerequisite()
- learning_module.save()
+ if unit_list:
+ for unit in unit_list:
+ learning_module = course.learning_module.get(id=unit)
+ learning_module.toggle_check_prerequisite()
+ learning_module.save()
+ messages.success(
+ request, "Changed prerequisite check successfully"
+ )
+ else:
+ messages.warning(request, "Please select atleast one module")
+
+ if "change_prerequisite_passing" in request.POST:
+ unit_list = request.POST.getlist("check_prereq_passes")
+ if unit_list:
+ for unit in unit_list:
+ learning_module = course.learning_module.get(id=unit)
+ learning_module.toggle_check_prerequisite_passes()
+ learning_module.save()
+ messages.success(
+ request, "Changed prerequisite check successfully"
+ )
+ else:
+ messages.warning(request, "Please select atleast one module")
added_learning_modules = course.get_learning_modules()
all_learning_modules = LearningModule.objects.filter(
@@ -2703,9 +2950,10 @@ def design_course(request, course_id):
learning_modules = set(all_learning_modules) - set(added_learning_modules)
context['added_learning_modules'] = added_learning_modules
context['learning_modules'] = learning_modules
- context['course_id'] = course_id
+ context['course'] = course
+ context['is_design_course'] = True
return my_render_to_response(
- request, 'yaksh/design_course_session.html', context
+ request, 'yaksh/course_detail.html', context
)
@@ -2727,11 +2975,19 @@ def view_module(request, module_id, course_id, msg=None):
return course_modules(request, course_id, msg)
all_modules = course.get_learning_modules()
if learning_module.has_prerequisite():
- if not learning_module.is_prerequisite_passed(user, course):
+ if not learning_module.is_prerequisite_complete(user, course):
msg = "You have not completed the module previous to {0}".format(
learning_module.name)
return course_modules(request, course_id, msg)
+ if learning_module.check_prerequisite_passes:
+ if not learning_module.is_prerequisite_passed(user, course):
+ msg = (
+ "You have not successfully passed the module"
+ " previous to {0}".format(learning_module.name)
+ )
+ return course_modules(request, course_id, msg)
+
learning_units = learning_module.get_learning_units()
context['learning_units'] = learning_units
context['learning_module'] = learning_module
@@ -2781,13 +3037,19 @@ def course_status(request, course_id):
course = get_object_or_404(Course, pk=course_id)
if not course.is_creator(user) and not course.is_teacher(user):
raise Http404('This course does not belong to you')
- students = course.get_only_students()
+ students = course.students.order_by("-id")
+ students_no = students.count()
+ paginator = Paginator(students, 100)
+ page = request.GET.get('page')
+ students = paginator.get_page(page)
+
stud_details = [(student, course.get_grade(student),
course.get_completion_percent(student),
- course.get_current_unit(student)) for student in students]
+ course.get_current_unit(student))
+ for student in students.object_list]
context = {
- 'course': course, 'student_details': stud_details,
- 'state': 'course_status'
+ 'course': course, 'objects': students, 'is_progress': True,
+ 'student_details': stud_details, 'students_no': students_no
}
return my_render_to_response(request, 'yaksh/course_detail.html', context)
@@ -2818,8 +3080,6 @@ def preview_questionpaper(request, questionpaper_id):
if not is_moderator(user):
raise Http404('You are not allowed to view this page!')
paper = QuestionPaper.objects.get(id=questionpaper_id)
- if not paper.quiz.creator == user:
- raise Http404('This questionpaper does not belong to you')
context = {
'questions': paper._get_questions_for_answerpaper(),
'paper': paper,
@@ -2876,6 +3136,8 @@ def get_user_data(request, course_id, student_id):
@email_verified
def download_course(request, course_id):
user = request.user
+ if not is_moderator(user):
+ raise Http404('You are not allowed to view this page!')
course = get_object_or_404(Course, pk=course_id)
if (not course.is_creator(user) and not course.is_teacher(user) and not
course.is_student(user)):
@@ -2888,10 +3150,11 @@ def download_course(request, course_id):
course_name = course.name.replace(" ", "_")
# Static files required for styling in html template
- static_files = {"js": ["bootstrap.js", "bootstrap.min.js",
- "jquery-1.9.1.min.js", "video.js"],
- "css": ["bootstrap.css", "bootstrap.min.css",
- "video-js.css", "offline.css"],
+ static_files = {"js": ["bootstrap.min.js",
+ "jquery-3.3.1.min.js", "video.js"],
+ "css": ["bootstrap.min.css",
+ "video-js.css", "offline.css",
+ "yakshcustom.css"],
"images": ["yaksh_banner.png"]}
zip_file = course.create_zip(current_dir, static_files)
zip_file.seek(0)
@@ -2901,3 +3164,76 @@ def download_course(request, course_id):
)
response.write(zip_file.read())
return response
+
+
+@login_required
+@email_verified
+def course_students(request, course_id):
+ user = request.user
+ if not is_moderator(user):
+ raise Http404('You are not allowed to view this page!')
+ course = get_object_or_404(Course, pk=course_id)
+ if not course.is_creator(user) and not course.is_teacher(user):
+ raise Http404("You are not allowed to view {0}".format(
+ course.name))
+ enrolled = course.get_enrolled()
+ requested = course.get_requests()
+ rejected = course.get_rejected()
+ context = {"enrolled": enrolled, "requested": requested, "course": course,
+ "rejected": rejected, "is_students": True}
+ return my_render_to_response(request, 'yaksh/course_detail.html', context)
+
+
+@login_required
+@email_verified
+def course_teachers(request, course_id):
+ user = request.user
+ if not is_moderator(user):
+ raise Http404('You are not allowed to view this page!')
+ course = get_object_or_404(Course, pk=course_id)
+ if not course.is_creator(user) and not course.is_teacher(user):
+ raise Http404("You are not allowed to view {0}".format(
+ course.name))
+ teachers = course.get_teachers()
+ context = {"teachers": teachers, "is_teachers": True, "course": course}
+ return my_render_to_response(request, 'yaksh/course_detail.html', context)
+
+
+@login_required
+@email_verified
+def get_course_modules(request, course_id):
+ user = request.user
+ if not is_moderator(user):
+ raise Http404('You are not allowed to view this page!')
+ course = get_object_or_404(Course, pk=course_id)
+ if not course.is_creator(user) and not course.is_teacher(user):
+ raise Http404("You are not allowed to view {0}".format(
+ course.name))
+ modules = course.get_learning_modules()
+ context = {"modules": modules, "is_modules": True, "course": course}
+ return my_render_to_response(request, 'yaksh/course_detail.html', context)
+
+
+@login_required
+@email_verified
+def download_course_progress(request, course_id):
+ user = request.user
+ if not is_moderator(user):
+ raise Http404('You are not allowed to view this page!')
+ course = get_object_or_404(Course, pk=course_id)
+ if not course.is_creator(user) and not course.is_teacher(user):
+ raise Http404('This course does not belong to you')
+ students = course.students.order_by("-id")
+ stud_details = [(student.get_full_name(), course.get_grade(student),
+ course.get_completion_percent(student),
+ course.get_current_unit(student))
+ for student in students]
+ response = HttpResponse(content_type='text/csv')
+ response['Content-Disposition'] = 'attachment; filename="{0}.csv"'.format(
+ (course.name).lower().replace(' ', '_'))
+ header = ['Name', 'Grade', 'Completion Percent', 'Current Unit']
+ writer = csv.writer(response)
+ writer.writerow(header)
+ for student in stud_details:
+ writer.writerow(student)
+ return response