summaryrefslogtreecommitdiff
path: root/yaksh
diff options
context:
space:
mode:
authorprathamesh2016-11-01 09:30:53 +0530
committerprathamesh2016-11-01 09:30:53 +0530
commit6f9d5d2779e64212988c0d164fa05ce2d05e696a (patch)
treee7a1c316b97df44ec701384feea421ca66e3aa9c /yaksh
parent3b66e5fb8af12ce756f34966bb684373062551dd (diff)
parentf563640af941a50642dc5eb6e63b1d63a1685046 (diff)
downloadonline_test-6f9d5d2779e64212988c0d164fa05ce2d05e696a.tar.gz
online_test-6f9d5d2779e64212988c0d164fa05ce2d05e696a.tar.bz2
online_test-6f9d5d2779e64212988c0d164fa05ce2d05e696a.zip
Merge branch 'master' of https://github.com/FOSSEE/online_test into UI-modifications
Resolved Conflicts: yaksh/templates/manage.html yaksh/templates/yaksh/design_questionpaper.html
Diffstat (limited to 'yaksh')
-rw-r--r--yaksh/bash_code_evaluator.py2
-rw-r--r--yaksh/bash_stdio_evaluator.py2
-rw-r--r--yaksh/code_evaluator.py3
-rw-r--r--yaksh/file_utils.py25
-rw-r--r--yaksh/forms.py15
-rw-r--r--yaksh/models.py70
-rw-r--r--yaksh/output/README.txt4
-rw-r--r--yaksh/static/yaksh/css/question_paper_creation.css12
-rw-r--r--yaksh/static/yaksh/js/question_paper_creation.js218
-rw-r--r--yaksh/templates/yaksh/add_question.html2
-rw-r--r--yaksh/templates/yaksh/add_quiz.html2
-rw-r--r--yaksh/templates/yaksh/ajax_questions.html31
-rw-r--r--yaksh/templates/yaksh/courses.html25
-rw-r--r--yaksh/templates/yaksh/design_questionpaper.html175
-rw-r--r--yaksh/test_views.py4
-rw-r--r--yaksh/urls.py8
-rw-r--r--yaksh/views.py192
17 files changed, 317 insertions, 473 deletions
diff --git a/yaksh/bash_code_evaluator.py b/yaksh/bash_code_evaluator.py
index e148fa8..e4b961c 100644
--- a/yaksh/bash_code_evaluator.py
+++ b/yaksh/bash_code_evaluator.py
@@ -22,10 +22,10 @@ class BashCodeEvaluator(CodeEvaluator):
def teardown(self):
# Delete the created file.
- super(BashCodeEvaluator, self).teardown()
os.remove(self.submit_code_path)
if self.files:
delete_files(self.files)
+ super(BashCodeEvaluator, self).teardown()
def check_code(self, user_answer, file_paths, test_case):
""" Function validates student script using instructor script as
diff --git a/yaksh/bash_stdio_evaluator.py b/yaksh/bash_stdio_evaluator.py
index e5e0da6..a7ea1a4 100644
--- a/yaksh/bash_stdio_evaluator.py
+++ b/yaksh/bash_stdio_evaluator.py
@@ -17,10 +17,10 @@ class BashStdioEvaluator(StdIOEvaluator):
self.submit_code_path = self.create_submit_code_file('Test.sh')
def teardown(self):
- super(BashStdioEvaluator, self).teardown()
os.remove(self.submit_code_path)
if self.files:
delete_files(self.files)
+ super(BashStdioEvaluator, self).teardown()
def compile_code(self, user_answer, file_paths, expected_input, expected_output):
self.files = []
diff --git a/yaksh/code_evaluator.py b/yaksh/code_evaluator.py
index 870a67f..79f616d 100644
--- a/yaksh/code_evaluator.py
+++ b/yaksh/code_evaluator.py
@@ -94,6 +94,9 @@ class CodeEvaluator(object):
# Private Protocol ##########
def setup(self):
+ if self.in_dir:
+ if not os.path.exists(self.in_dir):
+ os.makedirs(self.in_dir)
self._change_dir(self.in_dir)
def safe_evaluate(self, user_answer, test_case_data, file_paths=None):
diff --git a/yaksh/file_utils.py b/yaksh/file_utils.py
index afcf9e8..f41c531 100644
--- a/yaksh/file_utils.py
+++ b/yaksh/file_utils.py
@@ -1,6 +1,7 @@
import shutil
import os
import zipfile
+import tempfile
def copy_files(file_paths):
@@ -14,16 +15,19 @@ def copy_files(file_paths):
files.append(file_name)
shutil.copy(file_path, os.getcwd())
if extract:
- z_files = extract_files(file_name)
+ z_files, path = extract_files(file_name, os.getcwd())
for file in z_files:
files.append(file)
return files
-def delete_files(files):
- """ Delete Files from current directory """
-
- for file in files:
+def delete_files(files, file_path=None):
+ """ Delete Files from directory """
+ for file_name in files:
+ if file_path:
+ file = os.path.join(file_path, file_name)
+ else:
+ file = file_name
if os.path.exists(file):
if os.path.isfile(file):
os.remove(file)
@@ -31,13 +35,18 @@ def delete_files(files):
shutil.rmtree(file)
-def extract_files(zip_file):
+def extract_files(zip_file, path=None):
+ """ extract files from zip """
zfiles = []
if zipfile.is_zipfile(zip_file):
zip_file = zipfile.ZipFile(zip_file, 'r')
for z_file in zip_file.namelist():
zfiles.append(z_file)
- zip_file.extractall()
+ if path:
+ extract_path = path
+ else:
+ extract_path = tempfile.gettempdir()
+ zip_file.extractall(extract_path)
zip_file.close()
- return zfiles
+ return zfiles, extract_path
diff --git a/yaksh/forms.py b/yaksh/forms.py
index a12ce9a..1931fad 100644
--- a/yaksh/forms.py
+++ b/yaksh/forms.py
@@ -1,6 +1,6 @@
from django import forms
-from yaksh.models import get_model_class, Profile, Quiz, Question, TestCase, Course, StandardTestCase, StdioBasedTestCase
-
+from yaksh.models import get_model_class, Profile, Quiz, Question, TestCase, Course,\
+ QuestionPaper, StandardTestCase, StdioBasedTestCase
from django.contrib.auth import authenticate
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
@@ -177,7 +177,7 @@ class QuestionForm(forms.ModelForm):
class Meta:
model = Question
- exclude = ['user']
+ exclude = ['user', 'active']
class FileForm(forms.Form):
@@ -199,7 +199,7 @@ class QuestionFilterForm(forms.Form):
super(QuestionFilterForm, self).__init__(*args, **kwargs)
questions = Question.objects.filter(user_id=user.id)
points_list = questions.values_list('points', flat=True).distinct()
- points_options = [('select', 'Select Marks')]
+ points_options = [(None, 'Select Marks')]
points_options.extend([(point, point) for point in points_list])
self.fields['marks'] = forms.FloatField(widget=forms.Select\
(choices=points_options))
@@ -215,6 +215,7 @@ class CourseForm(forms.ModelForm):
model = Course
fields = ['name', 'active', 'enrollment']
+
class ProfileForm(forms.ModelForm):
""" profile form for students and moderators """
@@ -236,3 +237,9 @@ class ProfileForm(forms.ModelForm):
class UploadFileForm(forms.Form):
file = forms.FileField()
+
+
+class QuestionPaperForm(forms.ModelForm):
+ class Meta:
+ model = QuestionPaper
+ fields = ['shuffle_questions']
diff --git a/yaksh/models.py b/yaksh/models.py
index 444df4a..7f9eead 100644
--- a/yaksh/models.py
+++ b/yaksh/models.py
@@ -22,7 +22,7 @@ from os.path import join, abspath, dirname, exists
import shutil
import zipfile
import tempfile
-from .file_utils import extract_files
+from .file_utils import extract_files, delete_files
from yaksh.xmlrpc_clients import code_server
from django.conf import settings
@@ -174,7 +174,7 @@ class Course(models.Model):
demo_ques = Question()
demo_ques.create_demo_questions(user)
demo_que_ppr = QuestionPaper()
- demo_que_ppr.create_demo_quiz_ppr(demo_quiz)
+ demo_que_ppr.create_demo_quiz_ppr(demo_quiz, user)
success = True
else:
success = False
@@ -206,12 +206,6 @@ class Profile(models.Model):
"""Return the output directory for the user."""
user_dir = join(settings.OUTPUT_DIR, str(self.user.username))
- if not exists(user_dir):
- os.makedirs(user_dir)
- # Make it rwx by others.
- os.chmod(user_dir, stat.S_IROTH | stat.S_IWOTH | stat.S_IXOTH
- | stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR
- | stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP)
return user_dir
@@ -271,7 +265,7 @@ class Question(models.Model):
return json.dumps(question_data)
def dump_questions(self, question_ids, user):
- questions = Question.objects.filter(id__in=question_ids, user_id=user.id)
+ questions = Question.objects.filter(id__in=question_ids, user_id=user.id, active=True)
questions_dict = []
zip_file_name = string_io()
zip_file = zipfile.ZipFile(zip_file_name, "a")
@@ -290,7 +284,7 @@ class Question(models.Model):
question._add_json_to_zip(zip_file, questions_dict)
return zip_file_name
- def load_questions(self, questions_list, user):
+ def load_questions(self, questions_list, user, file_path=None, files_list=None):
questions = json.loads(questions_list)
for question in questions:
question['user'] = user
@@ -298,10 +292,12 @@ class Question(models.Model):
test_cases = question.pop('testcase')
que, result = Question.objects.get_or_create(**question)
if file_names:
- que._add_files_to_db(file_names)
+ que._add_files_to_db(file_names, file_path)
model_class = get_model_class(que.test_case_type)
for test_case in test_cases:
model_class.objects.get_or_create(question=que, **test_case)
+ if files_list:
+ delete_files(files_list, file_path)
def get_test_cases(self, **kwargs):
test_case_ctype = ContentType.objects.get(app_label="yaksh",
@@ -333,15 +329,18 @@ class Question(models.Model):
files_list.append(((os.path.basename(f.file.path)), f.extract))
return files_list
- def _add_files_to_db(self, file_names):
+ def _add_files_to_db(self, file_names, path):
for file_name, extract in file_names:
- que_file = open(file_name, 'r')
- #Converting to Python file object with some Django-specific additions
- django_file = File(que_file)
- FileUpload.objects.get_or_create(file=django_file,
- question=self,
- extract=extract)
- os.remove(file_name)
+ q_file = os.path.join(path, file_name)
+ if os.path.exists(q_file):
+ que_file = open(q_file, 'r')
+ # Converting to Python file object with
+ # some Django-specific additions
+ django_file = File(que_file)
+ file_upload = FileUpload()
+ file_upload.question = self
+ file_upload.extract = extract
+ file_upload.file.save(file_name, django_file, save=True)
def _add_json_to_zip(self, zip_file, q_dict):
json_data = json.dumps(q_dict, indent=2)
@@ -353,18 +352,18 @@ class Question(models.Model):
zip_file.close()
shutil.rmtree(tmp_file_path)
- def read_json(self, json_file, user):
+ def read_json(self, file_path, user, files=None):
+ json_file = os.path.join(file_path, "questions_dump.json")
if os.path.exists(json_file):
with open(json_file, 'r') as q_file:
questions_list = q_file.read()
- self.load_questions(questions_list, user)
- os.remove(json_file)
+ self.load_questions(questions_list, user, file_path, files)
def create_demo_questions(self, user):
zip_file_path = os.path.join(os.getcwd(), 'yaksh',
- 'fixtures', 'demo_questions.zip')
- extract_files(zip_file_path)
- self.read_json("questions_dump.json", user)
+ 'fixtures', 'demo_questions.zip')
+ files, extract_path = extract_files(zip_file_path)
+ self.read_json(extract_path, user, files)
def __str__(self):
@@ -604,10 +603,10 @@ class QuestionPaper(models.Model):
random_questions = models.ManyToManyField("QuestionSet")
# Option to shuffle questions, each time a new question paper is created.
- shuffle_questions = models.BooleanField(default=False)
+ shuffle_questions = models.BooleanField(default=False, blank=False)
# Total marks for the question paper.
- total_marks = models.FloatField()
+ total_marks = models.FloatField(default=0.0, blank=True)
objects = QuestionPaperManager()
@@ -623,8 +622,7 @@ class QuestionPaper(models.Model):
def _get_questions_for_answerpaper(self):
""" Returns fixed and random questions for the answer paper"""
- questions = []
- questions = list(self.fixed_questions.all())
+ questions = list(self.fixed_questions.filter(active=True))
for question_set in self.random_questions.all():
questions += question_set.get_random_questions()
return questions
@@ -674,13 +672,14 @@ class QuestionPaper(models.Model):
prerequisite = self._get_prequisite_paper()
return prerequisite._is_questionpaper_passed(user)
- def create_demo_quiz_ppr(self, demo_quiz):
+ def create_demo_quiz_ppr(self, demo_quiz, user):
question_paper = QuestionPaper.objects.create(quiz=demo_quiz,
- total_marks=5.0,
+ total_marks=7.0,
shuffle_questions=True
)
questions = Question.objects.filter(active=True,
- summary="Yaksh Demo Question")
+ summary="Yaksh Demo Question",
+ user=user)
# add fixed set of questions to the question paper
for question in questions:
question_paper.fixed_questions.add(question)
@@ -764,8 +763,9 @@ class AnswerPaperManager(models.Manager):
attempt_number)
questions = self.get_all_questions(questionpaper_id, attempt_number)
all_questions = Question.objects.filter(
- id__in=set(questions)
- ).order_by('type')
+ id__in=set(questions),
+ active=True
+ ).order_by('type')
for question in all_questions:
if question.id in questions_answered:
question_stats[question] = [questions_answered[question.id],
@@ -992,7 +992,7 @@ class AnswerPaper(models.Model):
return q_a
def get_questions(self):
- return self.questions.all()
+ return self.questions.filter(active=True)
def get_questions_answered(self):
return self.questions_answered.all()
diff --git a/yaksh/output/README.txt b/yaksh/output/README.txt
deleted file mode 100644
index 3163ed4..0000000
--- a/yaksh/output/README.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This directory contains files generated/saved by users as per their
-username. The test executor will chdir into this user directory for each
-user when they run the test. Do not delete this directory and ensure that
-it is writeable by all. \ No newline at end of file
diff --git a/yaksh/static/yaksh/css/question_paper_creation.css b/yaksh/static/yaksh/css/question_paper_creation.css
index c915320..588b65c 100644
--- a/yaksh/static/yaksh/css/question_paper_creation.css
+++ b/yaksh/static/yaksh/css/question_paper_creation.css
@@ -5,9 +5,6 @@ body {
line-height: 18px;
color: #404040;
}
-.clearfix {
- clear: both;
-}
.tabs li {
text-align: center;
width: 33%;
@@ -48,7 +45,7 @@ body {
padding: 7px 0;
border: 2px solid #f5f5f5;
}
-#selectors .span4 {
+#selectors .col-md-6 {
margin-left: 0;
}
#id_question_type {
@@ -57,8 +54,8 @@ body {
#id_marks {
width: 100%;
}
-#fixed-questions .span7 > div,
-#random-questions .span7 > div{
+#fixed-questions .col-md-6 > div,
+#random-questions .col-md-6 > div{
background: #f5f5f5;
height: 200px;
border: 1px solid #333333;
@@ -111,9 +108,6 @@ body {
.red-alert {
border: 2px solid red;
}
-#myModal .qcard .remove{
- display: none;
-}
.well{
padding: 5px;
}
diff --git a/yaksh/static/yaksh/js/question_paper_creation.js b/yaksh/static/yaksh/js/question_paper_creation.js
index a144540..898e491 100644
--- a/yaksh/static/yaksh/js/question_paper_creation.js
+++ b/yaksh/static/yaksh/js/question_paper_creation.js
@@ -1,204 +1,33 @@
$(document).ready(function(){
- /* selectors for the 3 step tabs*/
- $fixed_tab = $("#fixed-tab");
- $random_tab = $("#random-tab");
- $finish_tab = $("#finish-tab");
-
- $question_type = $("#id_question_type");
- $marks = $("#id_marks");
-
- $total_marks = $("#total_marks");
+ $question_type = $('#id_question_type');
+ $qpaper_id = $('#qpaper_id');
+ $marks = $('#id_marks');
+ $show = $('#show');
/* ajax requsts on selectors change */
$question_type.change(function() {
- $.ajax({
- url: "/exam/ajax/questionpaper/marks/",
- type: "POST",
- data: {
- question_type: $question_type.val()
- },
- dataType: "html",
- success: function(output) {
- $marks.html(output);
- }
- });
+ this.form.submit();
});
$marks.change(function() {
- var fixed_question_list = [];
- var fixed_inputs = $("input[name=fixed]");
- var random_question_list = [];
- var random_inputs = $("input[name=random]");
- for(var i = 0; i < fixed_inputs.length; i++){
- fixed_question_list.push($(fixed_inputs[i]).val());
- }
- for(var i = 0; i < random_inputs.length; i++){
- random_question_list.push($(random_inputs[i]).val());
- }
- $.ajax({
- url: "/exam/ajax/questionpaper/questions/",
- type: "POST",
- data: {
- question_type: $question_type.val(),
- marks: $marks.val(),
- fixed_list: fixed_question_list,
- random_list: random_question_list
- },
- dataType: "html",
- success: function(output) {
- if($fixed_tab.hasClass("active")) {
- var questions = $(output).filter("#questions").html();
- $("#fixed-available").html(questions);
- } else if($random_tab.hasClass("active")) {
- var questions = $(output).filter("#questions").html();
- var numbers = $(output).filter("#num").html();
- $("#random-available").html(questions);
- $("#number-wrapper").html(numbers);
- }
- }
- });
- });
-
- /* adding fixed questions */
- $("#add-fixed").click(function(e) {
- var count = 0;
- var selected = [];
- var html = "";
- var $element;
- var total_marks = parseFloat($total_marks.text());
- var marks_per = parseFloat($marks.val())
- $("#fixed-available input:checkbox").each(function(index, element) {
- if($(this).attr("checked")) {
- qid = $(this).attr("data-qid");
- if(!$(this).hasClass("ignore")) {
- selected.push(qid);
- $element = $("<div class='qcard'></div>");
- html += "<li>" + $(this).next().html() + "</li>";
- count++;
- }
- }
- });
- html = "<ul>" + html + "</ul>";
- selected = selected.join(",");
- var $input = $("<input type='hidden'>");
- $input.attr({
- value: selected,
- name: "fixed"
- });
- $remove = $("<a href='#' class='remove' data-num="+count+" data-marks = "+marks_per +">&times;</div>");
- $element.html(count + " question(s) added").append(html).append($input).append($remove);
- $("#fixed-added").prepend($element);
- total_marks = total_marks + count * marks_per;
- $total_marks.text(total_marks)
- e.preventDefault();
- });
-
- /* adding random questions */
- $("#add-random").click(function(e) {
- $numbers = $("#numbers");
- random_number = $numbers.val()
- if($numbers.val()) {
- $numbers.removeClass("red-alert");
- var count = 0;
- var selected = [];
- var html = "";
- var $element;
- var total_marks = parseFloat($total_marks.text());
- var marks_per = parseFloat($marks.val())
- $("#random-available input:checkbox").each(function(index, element) {
- if($(this).attr("checked")) {
- qid = $(this).attr("data-qid");
- if(!$(this).hasClass("ignore")) {
- selected.push(qid);
- $element = $("<div class='qcard'></div>");
- html += "<li>" + $(this).next().html() + "</li>";
- count++;
- }
- }
- });
- html = "<ul>" + html + "</ul>";
- selected = selected.join(",");
- var $input_random = $("<input type='hidden'>");
- $input_random.attr({
- value: selected,
- name: "random"
- });
- var $input_number = $("<input type='hidden'>");
- $input_number.attr({
- value: $numbers.val(),
- name: "number"
- });
- $remove = $("<a href='#' class='remove' data-num="+random_number+" data-marks = "+marks_per +">&times;</div>");
- $element.html(random_number + " question(s) will be selected from " + count + " question(s)").append(html).append($input_random).append($input_number).append($remove);
- $("#random-added").prepend($element);
- total_marks = total_marks + random_number * marks_per;
- $total_marks.text(total_marks)
- } else {
- $numbers.addClass("red-alert");
- }
- e.preventDefault();
- });
-
- /* removing added questions */
- $(".qcard .remove").live("click", function(e) {
- var marks_per = $(this).attr('data-marks');
- var num_question = $(this).attr('data-num');
- var sub_marks = marks_per*num_question;
- var total_marks = parseFloat($total_marks.text());
- total_marks = total_marks - sub_marks;
- $total_marks.text(total_marks);
-
- $(this).parent().slideUp("normal", function(){ $(this).remove(); });
- e.preventDefault();
+ this.form.submit();
});
/* showing/hiding selectors on tab click */
$(".tabs li").click(function() {
if($(this).attr("id") == "finish-tab") {
$("#selectors").hide();
+ $('#is_active').val("finish");
} else {
- $question_type.val('select');
- $marks.val('select')
- $("#selectors").show();
- }
- });
- /* check all questions on checked*/
- $("#checkall").live("click", function(){
- if($(this).attr("checked")) {
- if($("#fixed-tab").hasClass("active")) {
- $("#fixed-available input:checkbox").each(function(index, element) {
- $(this).attr('checked','checked');
- });
+ if($(this).attr("id") == "fixed-tab") {
+ $('#is_active').val("fixed");
}
- else {
- $("#random-available input:checkbox").each(function(index, element) {
- $(this).attr('checked','checked');
- });
+ if($(this).attr("id") == "random-tab") {
+ $('#is_active').val("random");
}
- }
- else {
- if($("#fixed-tab").hasClass("active")) {
- $("#fixed-available input:checkbox").each(function(index, element) {
- $(this).removeAttr('checked');
- });
- }
- else {
- $("#random-available input:checkbox").each(function(index, element) {
- $(this).removeAttr('checked');
- });
- }
- }
- });
-
- /* show preview on preview click */
- $("#preview").click(function(){
- questions = getQuestions()
- if(questions.trim() == ""){
- $('#modal_body').html("No questions selected");
+ $question_type.val('select');
+ $marks.val('select')
+ $("#selectors").show();
}
- else {
- $('#modal_body').html(questions);
- }
- $("#myModal").modal('show');
});
/* tab change on next or previous button click */
@@ -217,21 +46,4 @@ $(document).ready(function(){
$("#random").click();
});
- /* Check at least one question is present before saving */
- $('#save').click(function(){
- questions = getQuestions();
- if(questions.trim() == ""){
- $("#modalSave").modal("show");
- }
- else {
- document.forms["frm"].submit();
- }
- });
-
- /* Fetch selected questions */
- function getQuestions(){
- var fixed_div = $("#fixed-added").html();
- var random_div = $("#random-added").html();
- return fixed_div+random_div;
- }
-}); //document
+});//document
diff --git a/yaksh/templates/yaksh/add_question.html b/yaksh/templates/yaksh/add_question.html
index 9142bb7..c0d53f8 100644
--- a/yaksh/templates/yaksh/add_question.html
+++ b/yaksh/templates/yaksh/add_question.html
@@ -18,7 +18,7 @@
<center><table class="table">
<tr><td>Summary: <td>{{ form.summary }}{{ form.summary.errors }}
<tr><td> Language: <td> {{form.language}}{{form.language.errors}}
- <tr><td> Active: <td> {{ form.active }}{{form.active.errors}} &nbsp; Type: &nbsp;{{ form.type }}{{form.type.errors}}
+ <tr><td> Type: <td> {{ form.type }}{{form.type.errors}}
<tr><td>Points:<td><button class="btn-mini" type="button" onClick="increase(frm);">+</button>{{form.points }}<button class="btn-mini" type="button" onClick="decrease(frm);">-</button>{{ form.points.errors }}
<tr><td><strong>Rendered: </strong><td><p id='my'></p>
<tr><td>Description: <td>{{ form.description}} {{form.description.errors}}
diff --git a/yaksh/templates/yaksh/add_quiz.html b/yaksh/templates/yaksh/add_quiz.html
index c674f4b..97bf5a2 100644
--- a/yaksh/templates/yaksh/add_quiz.html
+++ b/yaksh/templates/yaksh/add_quiz.html
@@ -20,7 +20,7 @@
</table>
</center>
- <center><button class="btn" type="submit" id="submit" name="questionpaper">Design Question Paper</button>
+ <center><button class="btn" type="submit" id="submit" name="questionpaper"> Save </button>
<button class="btn" type="button" name="button" onClick='location.replace("{{URL_ROOT}}/exam/manage/courses/");'>Cancel</button> </center>
diff --git a/yaksh/templates/yaksh/ajax_questions.html b/yaksh/templates/yaksh/ajax_questions.html
deleted file mode 100644
index e343f9b..0000000
--- a/yaksh/templates/yaksh/ajax_questions.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<div id="questions">
- {% if questions %}
- <input type="checkbox" id="checkall" class="ignore">
- <span><b> <font size="3"> Select All </font></b></span>
- {% endif %}
- <ul class="inputs-list">
-
- {% for question in questions %}
- <li>
- <label>
- <input type="checkbox" name="questions" data-qid="{{question.id}}">
- <span> {{ question.summary }} </span>
- </label>
- </li>
- {% endfor %}
- </ul>
-</div>
-
-<div id="num">
- <select id="numbers">
- <option value="">Number of questions to be picked from the pool</option>
- {% for q in questions %}
- {% if forloop.counter0 != 0 %}
- <option value={{forloop.counter0}}>{{ forloop.counter0}}</option>
- {% endif %}
- {% if questions|length == 1%}
- <option value=1>1</option>
- {% endif %}
- {% endfor %}
- </select>
-</div>
diff --git a/yaksh/templates/yaksh/courses.html b/yaksh/templates/yaksh/courses.html
index 0a61d72..24e29af 100644
--- a/yaksh/templates/yaksh/courses.html
+++ b/yaksh/templates/yaksh/courses.html
@@ -18,11 +18,10 @@
{% if user != course.creator %}
<h4> {{course.creator.get_full_name}} added you to this course</h4>
{% endif %}
-
<div class="row show-grid">
<div class="span14">
<div class="row">
- <div class="span6">
+ <div class="span4">
<p>
<b><u>Course</u></b>
{% if course.active %}
@@ -35,7 +34,7 @@
</br></br>
{% if user == course.creator %}
<div class="row">
- <div class="span6 wrap">
+ <div class="span3 wrap">
<center><b><u>Teacher(s) Added to {{ course }}</u></b></center>
{% if course.get_teachers %}
<div align="left">
@@ -65,12 +64,23 @@
<p><b><a href="{{URL_ROOT}}/exam/manage/searchteacher/{{course.id}}/">Add Teacher</a></b></p>
</div>
{% endif %}
- <div class="span6">
- <p><b><u>Quiz(zes)</u></b></p>
+ <div class="span4" style="text-align:left">
{% if course.get_quizzes %}
- {% for quiz in course.get_quizzes %}
+ <p><b><u>Quiz(zes)</u></b></p>
+ {% for quiz in course.get_quizzes %}
<a href="{{URL_ROOT}}/exam/manage/addquiz/{{course.id}}/{{quiz.id}}/">{{ quiz.description }}</a><br>
-
+ {% endfor %}
+ </div>
+ <div class="span4" style="text-align:left">
+ <p><b><u>Question Paper(s)</u></b></p>
+ {% for quiz in course.get_quizzes %}
+ {% if quiz.questionpaper_set.get %}
+ <a href="{{URL_ROOT}}/exam/manage/designquestionpaper/{{ quiz.id }}/{{quiz.questionpaper_set.get.id}}/">Question Paper for {{ quiz.description }}</a><br>
+ {% else %}
+ <p><b>No Question Paper </b>
+ <button class="btn small primary" type="button" onClick='location.replace("{{URL_ROOT}}/exam/manage/quiz/designquestionpaper/{{ quiz.id }}/");'>Add</button>
+ </p>
+ {% endif %}
{% endfor %}
{% else %}
<p><b>No quiz </b></p>
@@ -79,7 +89,6 @@
</div>
<br/>
<button class="btn primary"type="button" onClick='location.replace("{{URL_ROOT}}/exam/manage/addquiz/{{course.id}}/");'>Add New Quiz</button>
-
</div>
</div>
<br><br>
diff --git a/yaksh/templates/yaksh/design_questionpaper.html b/yaksh/templates/yaksh/design_questionpaper.html
index 9c190b7..387402a 100644
--- a/yaksh/templates/yaksh/design_questionpaper.html
+++ b/yaksh/templates/yaksh/design_questionpaper.html
@@ -1,12 +1,12 @@
{% extends "manage.html" %}
-{% block subtitle %}Design Question Paper{% endblock %}
+{% block title %} Design Question Paper {% endblock title %}
+
+{% block subtitle %} Design Question Paper {% endblock %}
{% block css %}
-<link rel="stylesheet" href="{{ URL_ROOT }}/static/yaksh/css/base.css" type="text/css" />
-<link rel="stylesheet" href="{{ URL_ROOT }}/static/yaksh/css/question_quiz.css" type="text/css" />
-<link rel="stylesheet" media="all" type="text/css" href="{{ URL_ROOT }}/static/yaksh/css/autotaggit.css" />
-<link rel="stylesheet" media="all" type="text/css" href="{{ URL_ROOT }}/static/yaksh/css/question_paper_creation.css" />
+ <link rel="stylesheet" media="all" type="text/css" href="{{ URL_ROOT }}/static/yaksh/css/bootstrap.css" />
+ <link rel="stylesheet" media="all" type="text/css" href="{{ URL_ROOT }}/static/yaksh/css/question_paper_creation.css" />
<style>
select
{
@@ -14,17 +14,20 @@ select
}
</style>
{% endblock %}
-{% block script %}
-<script src="{{ URL_ROOT }}/static/yaksh/js/jquery-1.4.2.min.js" type="text/javascript"></script>
-<script src="{{ URL_ROOT }}/static/yaksh/js/bootstrap-tabs.js"></script>
-<script src="{{ URL_ROOT }}/static/yaksh/js/add_questionpaper.js"></script>
-<script src="{{ URL_ROOT }}/static/yaksh/js/question_paper_creation.js"></script>
-<script src="{{ URL_ROOT }}/static/yaksh/js/bootstrap-modal.js"></script>
+{% block script %}
+ <script src="{{ URL_ROOT }}/static/yaksh/js/jquery-1.9.1.min.js"></script>
+ <script src="{{ URL_ROOT }}/static/yaksh/js/bootstrap.js"></script>
+ <script src="{{ URL_ROOT }}/static/yaksh/js/bootstrap-tabs.js"></script>
+ <script src="{{ URL_ROOT }}/static/yaksh/js/question_paper_creation.js"></script>
{% endblock %}
{% block content %}
<input type=hidden id="url_root" value={{ URL_ROOT }}>
+<form action="{{ URL_ROOT }}/exam/manage/designquestionpaper/{{ qpaper.quiz.id }}/{{ qpaper.id }}/" method="POST">
+<input class ="btn primary small" type="submit" name="back" id="back" value="Cancel">
+ {% csrf_token %}
+ <input type=hidden name="is_active" id="is_active" value="{{ state }}">
<center><b>Manual mode to design the {{lang}} Question Paper</center><br>
<ul class="tabs" data-tabs="tabs">
<li class="active" id="fixed-tab">
@@ -46,42 +49,62 @@ select
</a></li>
</ul>
-<form action="{{URL_ROOT}}/exam/manage/designquestionpaper/" method="post" name=frm > {% csrf_token %}
<div>
- <h3>Total Marks: <span id="total_marks" class="well">0</span></h3>
+ <h3>Total Marks: <span id="total_marks" class="well"> {{ qpaper.total_marks }} </span></h3>
</div>
<div class="tab-content">
<!-- common to fixed and random questions -->
<div class="row" id="selectors">
<h5 style="padding-left: 20px;">Please select Question type and Marks</h5>
- <div class="span4">
- {{ form.question_type }}
- </div> <!-- /.span4 -->
- <div class="span4">
- {{ form.marks }}
- </div> <!-- /.span4 -->
- <div class="span4">
- <div class="pull-left" id="number-wrapper"></div>
- </div> <!-- /.span4 -->
+ <div class="col-md-6">
+ {{ filter_form.question_type }}
+ </div>
+ <div class="col-md-6">
+ {{ filter_form.marks }}
+ </div>
</div> <!-- /.row -->
<br><br>
-
<div class="tab-pane active" id="fixed-questions">
<div class="row">
- <div class="span7">
+ <div class="col-md-6">
<div id="fixed-available-wrapper">
<p><u>Select questions to add:</u></p>
<div id="fixed-available">
+ {% if state == "fixed" or state == "None" %}
+ <ul class="inputs-list">
+ {% for question in questions %}
+ <li>
+ <label>
+ <input type="checkbox" name="questions" data-qid="{{question.id}}" value={{question.id}}>
+ <span> {{ question.summary }} </span> <span> {{ question.points }} </span>
+ </label>
+ </li>
+ {% endfor %}
+ </ul>
+ {% endif %}
</div>
- <a id="add-fixed" class="btn small primary pull-right" href="#">Add to paper</a>
+ <br /><br />
+ <button id="add-fixed" name="add-fixed" class="btn small primary pull-right" type="submit">Add to paper</button>
</div>
</div>
- <div class="span7">
+ <div class="col-md-6">
<div id="fixed-added-wrapper">
<p><u>Fixed questions currently in paper:</u></p>
<div id="fixed-added">
+ <ul class="inputs-list">
+ {% for question in fixed_questions %}
+ <li>
+ <label>
+ <input type="checkbox" name="added-questions" data-qid="{{question.id}}" value={{question.id}}>
+ <span> {{ question.summary }} </span> <span> {{ question.points }} </span>
+ </label>
+ </li>
+ {% endfor %}
+ </ul>
</div>
+ <br />
+ <button id="remove-fixed" name="remove-fixed" class="btn small primary pull-right" type="submit"> Remove from paper</button>
</div>
</div>
</div> <!-- /.row -->
@@ -89,25 +112,66 @@ select
<div class="pull-right">
<a class="btn" id="fixed-next">Next &gt;</a>
</div>
-
</div> <!-- /#fixed-questions -->
-
<div class="tab-pane" id="random-questions">
<div class="row">
- <div class="span7">
+ <div class="col-md-6">
<div id="random-available-wrapper">
<p><u>Select questions to add to the pool:</u></p>
<div id="random-available">
+ {% if state == "random" %}
+ <select id="num_of_questions" name="num_of_questions">
+ <option value="1">Number of questions to be picked from the pool</option>
+ {% for q in questions %}
+ {% if forloop.counter0 != 0 %}
+ <option value={{forloop.counter0}}>{{ forloop.counter0}}</option>
+ {% endif %}
+ {% if questions|length == 1%}
+ <option value=1>1</option>
+ {% endif %}
+ {% endfor %}
+ </select>
+ <ul class="inputs-list">
+ {% for question in questions %}
+ <li>
+ <label>
+ <input type="checkbox" name="random_questions" data-qid="{{question.id}}" value={{question.id}}>
+ <span> {{ question.summary }} </span> <span> {{ question.points }} </span>
+ </label>
+ </li>
+ {% endfor %}
+ </ul>
+ {% endif %}
</div>
- <a id="add-random" class="btn small primary pull-right" href="#">Add to paper</a>
+ <br /><br />
+ <button id="add-random" name="add-random" class="btn small primary pull-right" type="submit">Add to paper</button>
</div>
</div>
- <div class="span7">
+ <div class="col-md-6">
<div id="random-added-wrapper">
<p><u>Pool of questions currently in paper:</u></p>
<div id="random-added">
+ <ul class="inputs-list">
+ {% for random_set in random_sets %}
+ <li>
+ <label>
+ <input type="checkbox" name="random_sets" data-qid="{{random_set.id}}" value={{random_set.id}}>
+ <span> Random Set {{ forloop.counter }} (will take {{ random_set.num_questions }} randomly out of {{ random_set.questions.count }})</span>
+ </label>
+ </li>
+ {% for question in random_set.questions.all %}
+ <li>
+ <label>
+ <span> {{ question.summary }} </span> <span> {{ question.points }} </span>
+ </label>
+ </li>
+ {% endfor %}
+ {% endfor %}
+ </ul>
</div>
+ <br />
+ <button id="remove-random" name="remove-random" class="btn small primary pull-right" type="submit"> Remove from paper</button>
</div>
</div>
</div> <!-- /.row -->
@@ -124,11 +188,10 @@ select
<center>
<h5>Almost finished creating your question paper</h5>
<label style="float: none;">
- {{ form.shuffle_questions }}
+ {{ qpaper_form.shuffle_questions }}
<span>Auto shuffle.</span>
</label> <br><br>
- <input class ="btn primary large" type="button" id="preview" value="Preview question paper">
- <input class ="btn primary large" type="button" id="save" value="Save question paper">
+ <input class ="btn primary large" type="submit" name="save" id="save" value="Save question paper">
<br>
<div class="pull-left">
<a class="btn" id="finish-prev">&lt; Previous</a>
@@ -139,44 +202,18 @@ select
<!-- /.tab-content -->
</form>
<br>
-<div class="clearfix"></div>
-
-<!-- Modal -->
-<div class="modal fade " id="myModal" >
- <div class="modal-dialog">
- <div class="modal-content">
- <div class="modal-header">
- <h4 class="modal-title" id="myModalLabel">Question Paper Preview</h4>
- </div>
- <div id = "modal_body"class="modal-body">
- </div>
- <div class="modal-footer">
- <button type="button" class="btn primary close" data-dismiss="modal">OK</button>
- </div>
- </div>
- </div>
-</div>
-
-<div class="modal fade " id="modalSave" >
- <div class="modal-dialog">
- <div class="modal-content">
- <div class="modal-header">
- <h4 class="modal-title" id="myModalLabel">Cannot Save</h4>
- </div>
- <div class="modal-body">
- Please select questions for your paper
- </div>
- <div class="modal-footer">
- <button type="button" class="btn primary close" data-dismiss="modal">OK</button>
- </div>
- </div>
- </div>
-</div>
-</div>
-
<script>
$(function () {
$('.tabs').tabs()
+ {% if state == "fixed" %}
+ $('#fixed').tab('show');
+ {% elif state == "random" %}
+ $("#random").tab('show');
+ {% elif state == "finish" %}
+ $('#finished').tab('show');
+ {% endif %}
})
</script>
{% endblock %}
+{% block manage %}
+{% endblock %}
diff --git a/yaksh/test_views.py b/yaksh/test_views.py
index cf547b5..1d1c3f3 100644
--- a/yaksh/test_views.py
+++ b/yaksh/test_views.py
@@ -294,7 +294,7 @@ class TestAddQuiz(TestCase):
self.assertEqual(updated_quiz.course, self.course)
self.assertEqual(response.status_code, 302)
- self.assertRedirects(response, '/exam/manage/')
+ self.assertRedirects(response, '/exam/manage/courses/')
def test_add_quiz_post_new_quiz(self):
"""
@@ -340,7 +340,7 @@ class TestAddQuiz(TestCase):
self.assertEqual(new_quiz.course, self.course)
self.assertEqual(response.status_code, 302)
- self.assertRedirects(response, '/exam/manage/designquestionpaper/')
+ self.assertRedirects(response, '/exam/manage/courses/')
class TestAddTeacher(TestCase):
def setUp(self):
diff --git a/yaksh/urls.py b/yaksh/urls.py
index c4619b6..bb8cf2e 100644
--- a/yaksh/urls.py
+++ b/yaksh/urls.py
@@ -68,9 +68,10 @@ urlpatterns += [
url(r'^manage/user_data/(?P<user_id>\d+)/(?P<questionpaper_id>\d+)/$',
views.user_data),
url(r'^manage/user_data/(?P<user_id>\d+)/$', views.user_data),
- url(r'^manage/designquestionpaper/$', views.design_questionpaper, name='design_questionpaper'),
- url(r'^manage/designquestionpaper/(?P<questionpaper_id>\d+)/$',\
- views.design_questionpaper),
+ url(r'^manage/quiz/designquestionpaper/(?P<quiz_id>\d+)/$', views.design_questionpaper,
+ name='design_questionpaper'),
+ url(r'^manage/designquestionpaper/(?P<quiz_id>\d+)/(?P<questionpaper_id>\d+)/$',
+ views.design_questionpaper, name='designquestionpaper'),
url(r'^manage/statistics/question/(?P<questionpaper_id>\d+)/$',
views.show_statistics),
url(r'^manage/statistics/question/(?P<questionpaper_id>\d+)/(?P<attempt_number>\d+)/$',
@@ -87,7 +88,6 @@ urlpatterns += [
url(r'manage/enrolled/reject/(?P<course_id>\d+)/(?P<user_id>\d+)/$',
views.reject, {'was_enrolled': True}),
url(r'manage/toggle_status/(?P<course_id>\d+)/$', views.toggle_course_status),
- url(r'^ajax/questionpaper/(?P<query>.+)/$', views.ajax_questionpaper),
url(r'^ajax/questions/filter/$', views.ajax_questions_filter),
url(r'^editprofile/$', views.edit_profile, name='edit_profile'),
url(r'^viewprofile/$', views.view_profile, name='view_profile'),
diff --git a/yaksh/views.py b/yaksh/views.py
index d6e54e2..2113477 100644
--- a/yaksh/views.py
+++ b/yaksh/views.py
@@ -29,7 +29,7 @@ from yaksh.models import Profile, Answer, AnswerPaper, User, TestCase, FileUploa
from yaksh.forms import UserRegisterForm, UserLoginForm, QuizForm,\
QuestionForm, RandomQuestionForm,\
QuestionFilterForm, CourseForm, ProfileForm, UploadFileForm,\
- get_object_form, FileForm
+ get_object_form, FileForm, QuestionPaperForm
from .settings import URL_ROOT
from yaksh.models import AssignmentUpload
from .file_utils import extract_files
@@ -246,7 +246,7 @@ def add_quiz(request, course_id, quiz_id=None):
form = QuizForm(request.POST, user=user, course=course_id)
if form.is_valid():
form.save()
- return my_redirect(reverse('yaksh:design_questionpaper'))
+ return my_redirect("/exam/manage/courses/")
else:
context["form"] = form
return my_render_to_response('yaksh/add_quiz.html',
@@ -259,7 +259,7 @@ def add_quiz(request, course_id, quiz_id=None):
if form.is_valid():
form.save()
context["quiz_id"] = quiz_id
- return my_redirect("/exam/manage/")
+ return my_redirect("/exam/manage/courses/")
else:
if quiz_id is None:
form = QuizForm(course=course_id, user=user)
@@ -415,8 +415,6 @@ def start(request, questionpaper_id=None, attempt_num=None):
msg = 'You do not have a profile and cannot take the quiz!'
raise Http404(msg)
new_paper = quest_paper.make_answerpaper(user, ip, attempt_num)
- # Make user directory.
- user_dir = new_paper.user.profile.get_user_dir()
return show_question(request, new_paper.current_question(), new_paper)
@@ -631,7 +629,6 @@ def courses(request):
raise Http404('You are not allowed to view this page')
courses = Course.objects.filter(creator=user, is_trial=False)
allotted_courses = Course.objects.filter(teachers=user, is_trial=False)
-
context = {'courses': courses, "allotted_courses": allotted_courses}
return my_render_to_response('yaksh/courses.html', context,
context_instance=ci)
@@ -813,6 +810,95 @@ def ajax_questions_filter(request):
{'questions': questions})
+def _get_questions(user, question_type, marks):
+ if question_type is None and marks is None:
+ return None
+ if question_type:
+ questions = Question.objects.filter(type=question_type, user=user)
+ if marks:
+ questions = questions.filter(points=marks)
+ return questions
+
+
+def _remove_already_present(questionpaper_id, questions):
+ if questionpaper_id is None:
+ return questions
+ questionpaper = QuestionPaper.objects.get(pk=questionpaper_id)
+ questions = questions.exclude(
+ id__in=questionpaper.fixed_questions.values_list('id', flat=True))
+ for random_set in questionpaper.random_questions.all():
+ questions = questions.exclude(
+ id__in=random_set.questions.values_list('id', flat=True))
+ return questions
+
+
+@login_required
+def design_questionpaper(request, quiz_id, questionpaper_id=None):
+ user = request.user
+
+ if not is_moderator(user):
+ raise Http404('You are not allowed to view this page!')
+
+ filter_form = QuestionFilterForm(user=user)
+ questions = None
+ marks = None
+ state = None
+ if questionpaper_id is None:
+ question_paper = QuestionPaper.objects.get_or_create(quiz_id=quiz_id)[0]
+ else:
+ question_paper = get_object_or_404(QuestionPaper, id=questionpaper_id)
+ qpaper_form = QuestionPaperForm(instance=question_paper)
+
+ if request.method == 'POST':
+
+ filter_form = QuestionFilterForm(request.POST, user=user)
+ qpaper_form = QuestionPaperForm(request.POST, instance=question_paper)
+ question_type = request.POST.get('question_type', None)
+ marks = request.POST.get('marks', None)
+ state = request.POST.get('is_active', None)
+
+ if 'add-fixed' in request.POST:
+ question_ids = request.POST.getlist('questions', None)
+ for question in Question.objects.filter(id__in=question_ids):
+ question_paper.fixed_questions.add(question)
+
+ if 'remove-fixed' in request.POST:
+ question_ids = request.POST.getlist('added-questions', None)
+ question_paper.fixed_questions.remove(*question_ids)
+
+ if 'add-random' in request.POST:
+ question_ids = request.POST.getlist('random_questions', None)
+ num_of_questions = request.POST.get('num_of_questions', 1)
+ if question_ids and marks:
+ random_set = QuestionSet(marks=marks, num_questions=num_of_questions)
+ random_set.save()
+ for question in Question.objects.filter(id__in=question_ids):
+ random_set.questions.add(question)
+ question_paper.random_questions.add(random_set)
+
+ if 'remove-random' in request.POST:
+ random_set_ids = request.POST.getlist('random_sets', None)
+ question_paper.random_questions.remove(*random_set_ids)
+
+ if 'save' in request.POST or 'back' in request.POST:
+ qpaper_form.save()
+ return my_redirect('/exam/manage/courses/')
+
+ if marks:
+ questions = _get_questions(user, question_type, marks)
+ questions = _remove_already_present(questionpaper_id, questions)
+
+ question_paper.update_total_marks()
+ question_paper.save()
+ random_sets = question_paper.random_questions.all()
+ fixed_questions = question_paper.fixed_questions.all()
+ context = {'qpaper_form': qpaper_form, 'filter_form': filter_form, 'qpaper':
+ question_paper, 'questions': questions, 'fixed_questions': fixed_questions,
+ 'state': state, 'random_sets': random_sets}
+ return my_render_to_response('yaksh/design_questionpaper.html', context,
+ context_instance=RequestContext(request))
+
+
@login_required
def show_all_questions(request):
"""Show a list of all the questions currently in the database."""
@@ -827,12 +913,10 @@ def show_all_questions(request):
if request.POST.get('delete') == 'delete':
data = request.POST.getlist('question')
if data is not None:
- questions = Question.objects.filter(id__in=data, user_id=user.id)
- files = FileUpload.objects.filter(question_id__in=questions)
- if files:
- for file in files:
- file.remove()
- questions.delete()
+ questions = Question.objects.filter(id__in=data, user_id=user.id, active=True)
+ for question in questions:
+ question.active = False
+ question.save()
if request.POST.get('upload') == 'upload':
form = UploadFileForm(request.POST, request.FILES)
@@ -841,8 +925,8 @@ def show_all_questions(request):
file_name = questions_file.name.split('.')
if file_name[-1] == "zip":
ques = Question()
- extract_files(questions_file)
- ques.read_json("questions_dump.json", user)
+ files, extract_path = extract_files(questions_file)
+ ques.read_json(extract_path, user, files)
else:
message = "Please Upload a ZIP file"
context['message'] = message
@@ -871,7 +955,7 @@ def show_all_questions(request):
else:
context["msg"] = "Please select atleast one question to test"
- questions = Question.objects.filter(user_id=user.id)
+ questions = Question.objects.filter(user_id=user.id, active=True)
form = QuestionFilterForm(user=user)
upload_form = UploadFileForm()
context['papers'] = []
@@ -999,80 +1083,6 @@ def grade_user(request, quiz_id=None, user_id=None, attempt_number=None):
)
-@csrf_exempt
-def ajax_questionpaper(request, query):
- """
- During question paper creation, ajax call made to get question details.
- """
-
- user = request.user
- if query == 'marks':
- question_type = request.POST.get('question_type')
- questions = Question.objects.filter(type=question_type, user=user)
- marks = questions.values_list('points').distinct()
- return my_render_to_response('yaksh/ajax_marks.html', {'marks': marks})
- elif query == 'questions':
- question_type = request.POST['question_type']
- marks_selected = request.POST['marks']
- fixed_questions = request.POST.getlist('fixed_list[]')
- fixed_question_list = ",".join(fixed_questions).split(',')
- random_questions = request.POST.getlist('random_list[]')
- random_question_list = ",".join(random_questions).split(',')
- question_list = fixed_question_list + random_question_list
- questions = list(Question.objects.filter(type=question_type,
- points=marks_selected, user=user))
- questions = [question for question in questions \
- if not str(question.id) in question_list]
- return my_render_to_response('yaksh/ajax_questions.html',
- {'questions': questions})
-
-
-@login_required
-def design_questionpaper(request):
- user = request.user
- ci = RequestContext(request)
-
- if not is_moderator(user):
- raise Http404('You are not allowed to view this page!')
-
- if request.method == 'POST':
- fixed_questions = request.POST.getlist('fixed')
- random_questions = request.POST.getlist('random')
- random_number = request.POST.getlist('number')
- is_shuffle = request.POST.get('shuffle_questions', False)
- if is_shuffle == 'on':
- is_shuffle = True
-
- question_paper = QuestionPaper(shuffle_questions=is_shuffle)
- quiz = Quiz.objects.order_by("-id")[0]
- tot_marks = 0
- question_paper.quiz = quiz
- question_paper.total_marks = tot_marks
- question_paper.save()
- if fixed_questions:
- fixed_questions_ids = ",".join(fixed_questions)
- fixed_questions_ids_list = fixed_questions_ids.split(',')
- for question_id in fixed_questions_ids_list:
- question_paper.fixed_questions.add(question_id)
- if random_questions:
- for random_question, num in zip(random_questions, random_number):
- qid = random_question.split(',')[0]
- question = Question.objects.get(id=int(qid))
- marks = question.points
- question_set = QuestionSet(marks=marks, num_questions=num)
- question_set.save()
- for question_id in random_question.split(','):
- question_set.questions.add(question_id)
- question_paper.random_questions.add(question_set)
- question_paper.update_total_marks()
- question_paper.save()
- return my_redirect('/exam/manage/courses')
- else:
- form = RandomQuestionForm()
- context = {'form': form, 'questionpaper':True}
- return my_render_to_response('yaksh/design_questionpaper.html',
- context, context_instance=ci)
-
@login_required
def view_profile(request):
""" view moderators and users profile """
@@ -1151,7 +1161,6 @@ def search_teacher(request, course_id):
Q(id=course.creator.id))
context['success'] = True
context['teachers'] = teachers
-
return my_render_to_response('yaksh/addteacher.html', context,
context_instance=ci)
@@ -1180,7 +1189,6 @@ def add_teacher(request, course_id):
course.add_teachers(*teachers)
context['status'] = True
context['teachers_added'] = teachers
-
return my_render_to_response('yaksh/addteacher.html', context,
context_instance=ci)
@@ -1188,7 +1196,7 @@ def add_teacher(request, course_id):
@login_required
def remove_teachers(request, course_id):
""" remove user from a course """
-
+
user = request.user
course = get_object_or_404(Course, pk=course_id)
if not is_moderator(user) and (user != course.creator and user not in course.teachers.all()):