summaryrefslogtreecommitdiff
path: root/yaksh
diff options
context:
space:
mode:
authorKing2018-07-12 02:29:40 -0700
committerGitHub2018-07-12 02:29:40 -0700
commita850749942d163f9aedb19a1d19c4b8d7016745d (patch)
tree9b93d232ad093f595a5e62d22f5d2a6af9629602 /yaksh
parente3ad85ace916354ab96b23c1359ee72a6c2a740b (diff)
parent0e2910668a8b2c79dd422cd49813e263f117b00d (diff)
downloadonline_test-a850749942d163f9aedb19a1d19c4b8d7016745d.tar.gz
online_test-a850749942d163f9aedb19a1d19c4b8d7016745d.tar.bz2
online_test-a850749942d163f9aedb19a1d19c4b8d7016745d.zip
Merge pull request #489 from adityacp/search_tags_in_design_qp
Get questions using tags during question paper setup
Diffstat (limited to 'yaksh')
-rw-r--r--yaksh/forms.py1
-rw-r--r--yaksh/static/yaksh/js/question_paper_creation.js9
-rw-r--r--yaksh/templates/yaksh/ajax_question_filter.html57
-rw-r--r--yaksh/templates/yaksh/design_questionpaper.html38
-rw-r--r--yaksh/test_views.py159
-rw-r--r--yaksh/views.py65
6 files changed, 288 insertions, 41 deletions
diff --git a/yaksh/forms.py b/yaksh/forms.py
index 41c9176..99e8dbe 100644
--- a/yaksh/forms.py
+++ b/yaksh/forms.py
@@ -258,6 +258,7 @@ class QuestionFilterForm(forms.Form):
self.fields['marks'] = forms.FloatField(
widget=forms.Select(choices=points_options)
)
+ self.fields['marks'].required = False
language = forms.CharField(
max_length=8, widget=forms.Select(choices=languages))
question_type = forms.CharField(
diff --git a/yaksh/static/yaksh/js/question_paper_creation.js b/yaksh/static/yaksh/js/question_paper_creation.js
index 430ec4b..86294b3 100644
--- a/yaksh/static/yaksh/js/question_paper_creation.js
+++ b/yaksh/static/yaksh/js/question_paper_creation.js
@@ -61,3 +61,12 @@ $(document).ready(function(){
});
});//document
+function append_tag(tag){
+ var tag_name = document.getElementById("question_tags");
+ if (tag_name.value != null){
+ tag_name.value = tag.value+", "+tag_name.value;
+ }
+ else{
+ tag_name.value = tag.value;
+ }
+} \ No newline at end of file
diff --git a/yaksh/templates/yaksh/ajax_question_filter.html b/yaksh/templates/yaksh/ajax_question_filter.html
index a63354c..ea0d0b5 100644
--- a/yaksh/templates/yaksh/ajax_question_filter.html
+++ b/yaksh/templates/yaksh/ajax_question_filter.html
@@ -1,16 +1,49 @@
<div id="questions">
+ <script>
+ $(document).ready(function(){
+ $("#checkall").change(function(){
+ if($(this).prop("checked")) {
+ $("#filtered-questions input:checkbox").each(function(index, element) {
+ $(this).prop('checked', true);
+ });
+ }
+ else {
+ $("#filtered-questions input:checkbox").each(function(index, element) {
+ $(this).prop('checked', false);
+ });
+ }
+ });
+ });
+ </script>
{% if questions %}
- <h5 class="highlight"><input type="checkbox" id="checkall" class="ignore"> Select All </h5>
+ <h5 class="highlight"><input type="checkbox" id="checkall">
+ Select All
+ </h5>
+ <ul class="inputs-list">
+ <table id="questions-table" class="tablesorter table table table-striped">
+ <thead>
+ <tr>
+ <th> Select </th>
+ <th> Summary </th>
+ <th> Language </th>
+ <th> Type </th>
+ <th> Marks </th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for question in questions %}
+ <tr>
+ <td>
+ <input type="checkbox" name="question" value="{{ question.id }}">
+ </td>
+ <td><a href="{{URL_ROOT}}/exam/manage/addquestion/{{ question.id }}">{{question.summary|capfirst}}</a></td>
+ <td>{{question.language|capfirst}}</td>
+ <td>{{question.type|capfirst}}</td>
+ <td>{{question.points}}</td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ </ul>
{% endif %}
- <ul class="inputs-list">
-
- {% for question in questions %}
- <li>
- <label>
- <input type="checkbox" name="question" data-qid="{{question.id}}" value=
- "{{question.id}}">&nbsp;&nbsp;<a href="{{URL_ROOT}}/exam/manage/addquestion/{{ question.id }}">{{ question }}</a><br>
- </label>
- </li>
- {% endfor %}
- </ul>
</div>
diff --git a/yaksh/templates/yaksh/design_questionpaper.html b/yaksh/templates/yaksh/design_questionpaper.html
index d982d27..7e6d5c0 100644
--- a/yaksh/templates/yaksh/design_questionpaper.html
+++ b/yaksh/templates/yaksh/design_questionpaper.html
@@ -68,8 +68,36 @@ select
</div>
</div> <!-- /.row -->
<br><br>
-
+ {% csrf_token %}
<div class="tab-pane active" id="fixed-questions">
+ <h4 style="padding-left: 20px;">Or</h4>
+ <!-- Search questions using tags -->
+ <h4 style="padding-left: 20px;">Search using Tags: </h4>
+ <div class="col-md-14">
+ <div class="input-group">
+ <span class="input-group-addon" id="basic-addon1">Search Questions </span>
+ <input type="text" id="question_tags" name="question_tags" class="form-control"
+ placeholder="Search using comma separated Tags">
+ <span class="input-group-btn">
+ <button class="btn btn-default" type="submit">Search</button>
+ </span>
+ <div class="col-md-6">
+ <select class="form-control" id="sel1" onchange="append_tag(this);">
+ {% if all_tags %}
+ <option value="" disabled selected>Available Tags</option>
+ {% for tag in all_tags %}
+ <option>
+ {{tag}}
+ </option>
+ {% endfor %}
+ {% else %}
+ <option value="" disabled selected>No Available Tags</option>
+ {% endif %}
+ </select>
+ </div>
+ </div>
+ </div>
+ <br><br>
<div class="row">
<div class="col-md-6">
<div id="fixed-available-wrapper">
@@ -116,7 +144,7 @@ select
</div> <!-- /.row -->
<br>
<div class="pull-right">
- <a class="btn" id="fixed-next">Next &gt;</a>
+ <a class="btn btn-primary" id="fixed-next">Next &gt;</a>
</div>
</div> <!-- /#fixed-questions -->
@@ -183,10 +211,10 @@ select
</div> <!-- /.row -->
<br>
<div class="pull-left">
- <a class="btn" id="random-prev">&lt; Previous</a>
+ <a class="btn btn-primary" id="random-prev">&lt; Previous</a>
</div>
<div class="pull-right">
- <a class="btn" id="random-next">Next &gt;</a>
+ <a class="btn btn-primary" id="random-next">Next &gt;</a>
</div>
</div> <!-- /#random-questions -->
@@ -204,7 +232,7 @@ select
<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>
+ <a class="btn btn-primary" id="finish-prev">&lt; Previous</a>
</div>
</center>
</div> <!-- /#finish -->
diff --git a/yaksh/test_views.py b/yaksh/test_views.py
index 8592031..24cf7d8 100644
--- a/yaksh/test_views.py
+++ b/yaksh/test_views.py
@@ -4373,6 +4373,24 @@ class TestQuestionPaper(TestCase):
timezone='UTC'
)
+ self.student_plaintext_pass = 'demo'
+ self.student = User.objects.create_user(
+ username='demo_student',
+ password=self.student_plaintext_pass,
+ first_name='first_name',
+ last_name='last_name',
+ email='demo@test.com'
+ )
+
+ Profile.objects.create(
+ user=self.student,
+ roll_number=10,
+ institute='IIT',
+ department='Chemical',
+ position='Student',
+ timezone='UTC'
+ )
+
self.user2_plaintext_pass = 'demo2'
self.user2 = User.objects.create_user(
username='demo_user2',
@@ -4435,6 +4453,15 @@ class TestQuestionPaper(TestCase):
creator=self.user
)
+ self.quiz_without_qp = Quiz.objects.create(
+ start_date_time=datetime(2014, 10, 9, 10, 8, 15, 0, tzone),
+ end_date_time=datetime(2015, 10, 9, 10, 8, 15, 0, tzone),
+ duration=30, active=True, instructions="Demo Instructions",
+ attempts_allowed=-1, time_between_attempts=0,
+ description='quiz without question paper', pass_criteria=40,
+ creator=self.user
+ )
+
self.learning_unit = LearningUnit.objects.create(
order=1, type="quiz", quiz=self.quiz)
self.learning_module = LearningModule.objects.create(
@@ -4517,6 +4544,13 @@ class TestQuestionPaper(TestCase):
)
self.float_based_testcase.save()
+ # Question with tag
+ self.tagged_que = Question.objects.create(
+ summary="Test_tag_question", description="Test Tag",
+ points=1.0, language="python", type="float", user=self.teacher
+ )
+ self.tagged_que.tags.add("test_tag")
+
self.questions_list = [self.question_mcq, self.question_mcc,
self.question_int, self.question_str,
self.question_float]
@@ -4529,6 +4563,13 @@ class TestQuestionPaper(TestCase):
quiz=self.quiz,
total_marks=5.0, fixed_question_order=questions_order
)
+ self.fixed_que = Question.objects.create(
+ summary="Test_fixed_question", description="Test Tag",
+ points=1.0, language="python", type="float", user=self.teacher
+ )
+ self.fixed_question_paper = QuestionPaper.objects.create(
+ quiz=self.demo_quiz, total_marks=5.0
+ )
self.question_paper.fixed_questions.add(*self.questions_list)
self.answerpaper = AnswerPaper.objects.create(
user=self.user, question_paper=self.question_paper,
@@ -4883,6 +4924,26 @@ class TestQuestionPaper(TestCase):
"questionpaper_id": self.question_paper.id}))
self.assertEqual(response.status_code, 404)
+ # Design question paper for a quiz
+ response = self.client.post(
+ reverse('yaksh:design_questionpaper',
+ kwargs={"quiz_id": self.quiz_without_qp.id}),
+ data={"marks": "1.0", "question_type": "code"})
+ self.assertEqual(response.status_code, 200)
+ self.assertIsNotNone(response.context['questions'])
+
+ # Student should not be able to design question paper
+ self.client.login(
+ username=self.student.username,
+ password=self.student_plaintext_pass
+ )
+
+ response = self.client.get(
+ reverse('yaksh:designquestionpaper',
+ kwargs={"quiz_id": self.demo_quiz.id,
+ "questionpaper_id": self.question_paper.id}))
+ self.assertEqual(response.status_code, 404)
+
self.client.login(
username=self.teacher.username,
password=self.teacher_plaintext_pass
@@ -4919,6 +4980,18 @@ class TestQuestionPaper(TestCase):
self.questions_list)
self.assertEqual(response.context['qpaper'], self.question_paper)
+ # Get questions using tags for question paper
+ search_tag = [tag for tag in self.tagged_que.tags.all()]
+ response = self.client.post(
+ reverse('yaksh:designquestionpaper',
+ kwargs={"quiz_id": self.quiz.id,
+ "course_id": self.course.id,
+ "questionpaper_id": self.question_paper.id}),
+ data={"question_tags": search_tag})
+
+ self.assertEqual(response.context["questions"][0], self.tagged_que)
+
+ # Add random questions in question paper
response = self.client.post(
reverse('yaksh:designquestionpaper',
kwargs={"quiz_id": self.quiz.id,
@@ -4929,6 +5002,7 @@ class TestQuestionPaper(TestCase):
'marks': ['1.0'], 'question_type': ['code'],
'add-random': ['']}
)
+
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'yaksh/design_questionpaper.html')
random_set = response.context['random_sets'][0]
@@ -4936,6 +5010,91 @@ class TestQuestionPaper(TestCase):
self.assertIn(self.random_que1, added_random_ques)
self.assertIn(self.random_que2, added_random_ques)
+ # Check if questions already exists
+ self.client.login(
+ username=self.user.username,
+ password=self.user_plaintext_pass
+ )
+ response = self.client.post(
+ reverse('yaksh:designquestionpaper',
+ kwargs={"quiz_id": self.quiz.id,
+ "course_id": self.course.id,
+ "questionpaper_id": self.question_paper.id}),
+ data={'marks': ['1.0'], 'question_type': ['code'],
+ 'add-fixed': ['']}
+ )
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.context["questions"].count(), 0)
+
+ # Add fixed question in question paper
+ response = self.client.post(
+ reverse('yaksh:designquestionpaper',
+ kwargs={"quiz_id": self.demo_quiz.id,
+ "course_id": self.course.id,
+ "questionpaper_id": self.fixed_question_paper.id}),
+ data={'checked_ques': [self.fixed_que.id],
+ 'add-fixed': ''}
+ )
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.context['qpaper'], self.fixed_question_paper)
+ self.assertEqual(response.context['fixed_questions'][0],
+ self.fixed_que)
+
+ # Add one more fixed question in question paper
+ response = self.client.post(
+ reverse('yaksh:designquestionpaper',
+ kwargs={"quiz_id": self.demo_quiz.id,
+ "course_id": self.course.id,
+ "questionpaper_id": self.fixed_question_paper.id}),
+ data={'checked_ques': [self.question_float.id],
+ 'add-fixed': ''}
+ )
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.context['qpaper'], self.fixed_question_paper)
+ self.assertEqual(response.context['fixed_questions'],
+ [self.fixed_que, self.question_float])
+
+ # Remove fixed question from question paper
+ response = self.client.post(
+ reverse('yaksh:designquestionpaper',
+ kwargs={"quiz_id": self.demo_quiz.id,
+ "course_id": self.course.id,
+ "questionpaper_id": self.fixed_question_paper.id}),
+ data={'added-questions': [self.fixed_que.id],
+ 'remove-fixed': ''}
+ )
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.context['qpaper'], self.fixed_question_paper)
+ self.assertEqual(response.context['fixed_questions'],
+ [self.question_float])
+
+ # Remove one more fixed question from question paper
+ response = self.client.post(
+ reverse('yaksh:designquestionpaper',
+ kwargs={"quiz_id": self.demo_quiz.id,
+ "course_id": self.course.id,
+ "questionpaper_id": self.fixed_question_paper.id}),
+ data={'added-questions': [self.question_float.id],
+ 'remove-fixed': ''}
+ )
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.context['qpaper'], self.fixed_question_paper)
+ self.assertEqual(response.context['fixed_questions'], [])
+
+ # Remove random questions from question paper
+ random_que_set = self.question_paper.random_questions.all().first()
+ response = self.client.post(
+ reverse('yaksh:designquestionpaper',
+ kwargs={"quiz_id": self.quiz.id,
+ "course_id": self.course.id,
+ "questionpaper_id": self.question_paper.id}),
+ data={'random_sets': random_que_set.id,
+ 'remove-random': ''}
+ )
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.context['qpaper'], self.question_paper)
+ self.assertEqual(len(response.context['random_sets']), 0)
+
class TestLearningModule(TestCase):
def setUp(self):
diff --git a/yaksh/views.py b/yaksh/views.py
index 3341aca..9116026 100644
--- a/yaksh/views.py
+++ b/yaksh/views.py
@@ -1232,16 +1232,15 @@ def ajax_questions_filter(request):
question_type = request.POST.get('question_type')
marks = request.POST.get('marks')
language = request.POST.get('language')
-
- if question_type != "select":
+ if question_type:
filter_dict['type'] = str(question_type)
- if marks != "select":
+ if marks:
filter_dict['points'] = marks
- if language != "select":
+ if language:
filter_dict['language'] = str(language)
- questions = list(Question.objects.filter(**filter_dict))
+ questions = Question.objects.filter(**filter_dict)
return my_render_to_response(
request, 'yaksh/ajax_question_filter.html', {'questions': questions}
@@ -1267,19 +1266,29 @@ def _remove_already_present(questionpaper_id, questions):
return questions
questionpaper = QuestionPaper.objects.get(pk=questionpaper_id)
questions = questions.exclude(
- id__in=questionpaper.fixed_questions.values_list('id', flat=True))
+ 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))
+ id__in=random_set.questions.values_list('id', flat=True))
return questions
+def _get_questions_from_tags(question_tags, user):
+ 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()
+
+
@login_required
@email_verified
def design_questionpaper(request, quiz_id, questionpaper_id=None,
course_id=None):
user = request.user
-
+ que_tags = Question.objects.filter(
+ active=True, user=user).values_list('tags', flat=True).distinct()
+ all_tags = Tag.objects.filter(id__in=que_tags)
if not is_moderator(user):
raise Http404('You are not allowed to view this page!')
if quiz_id:
@@ -1309,18 +1318,24 @@ def design_questionpaper(request, quiz_id, questionpaper_id=None,
question_type = request.POST.get('question_type', None)
marks = request.POST.get('marks', None)
state = request.POST.get('is_active', None)
+ tags = request.POST.get('question_tags', None)
if 'add-fixed' in request.POST:
question_ids = request.POST.get('checked_ques', None)
- if question_paper.fixed_question_order:
- ques_order = question_paper.fixed_question_order.split(",") +\
- question_ids.split(",")
- questions_order = ",".join(ques_order)
- else:
- questions_order = question_ids
- questions = Question.objects.filter(id__in=question_ids.split(','))
- question_paper.fixed_question_order = questions_order
- question_paper.save()
- question_paper.fixed_questions.add(*questions)
+ if question_ids:
+ if question_paper.fixed_question_order:
+ ques_order = (
+ question_paper.fixed_question_order.split(",") +
+ question_ids.split(",")
+ )
+ questions_order = ",".join(ques_order)
+ else:
+ questions_order = question_ids
+ questions = Question.objects.filter(
+ id__in=question_ids.split(',')
+ )
+ question_paper.fixed_question_order = questions_order
+ question_paper.save()
+ question_paper.fixed_questions.add(*questions)
if 'remove-fixed' in request.POST:
question_ids = request.POST.getlist('added-questions', None)
@@ -1356,6 +1371,11 @@ def design_questionpaper(request, quiz_id, questionpaper_id=None,
if marks:
questions = _get_questions(user, question_type, marks)
+ elif tags:
+ que_tags = request.POST.getlist('question_tags', None)
+ questions = _get_questions_from_tags(que_tags, user)
+
+ if questions:
questions = _remove_already_present(questionpaper_id, questions)
question_paper.update_total_marks()
@@ -1370,7 +1390,8 @@ def design_questionpaper(request, quiz_id, questionpaper_id=None,
'fixed_questions': fixed_questions,
'state': state,
'random_sets': random_sets,
- 'course_id': course_id
+ 'course_id': course_id,
+ 'all_tags': all_tags
}
return my_render_to_response(
request, 'yaksh/design_questionpaper.html', context
@@ -1453,11 +1474,7 @@ def show_all_questions(request):
if request.POST.get('question_tags'):
question_tags = request.POST.getlist("question_tags")
- search_tags = []
- for tags in question_tags:
- search_tags.extend(re.split('[; |, |\*|\n]', tags))
- search_result = Question.objects.filter(tags__name__in=search_tags,
- user=user).distinct()
+ search_result = _get_questions_from_tags(question_tags, user)
context['questions'] = search_result
return my_render_to_response(request, 'yaksh/showquestions.html', context)