From c557e19470a389aaac569516ed56e1c5b453fd88 Mon Sep 17 00:00:00 2001 From: ankitjavalkar Date: Tue, 26 Apr 2016 19:37:42 +0530 Subject: Add views, forms and templates (with JS) for new test cases: - Add a view and template to list out test cases for particular question - Add a view and template to add/edit test cases --- yaksh/forms.py | 22 ++++++- yaksh/models.py | 44 ++++++++++--- yaksh/static/yaksh/js/show_testcase.js | 24 +++++++ yaksh/templates/yaksh/add_question.html | 15 +++-- yaksh/templates/yaksh/add_testcase.html | 32 +++++++--- yaksh/templates/yaksh/show_testcase.html | 31 +++++++++ yaksh/views.py | 104 ++++++++++++++++++++++++------- 7 files changed, 228 insertions(+), 44 deletions(-) create mode 100644 yaksh/static/yaksh/js/show_testcase.js create mode 100644 yaksh/templates/yaksh/show_testcase.html (limited to 'yaksh') diff --git a/yaksh/forms.py b/yaksh/forms.py index 1375d10..9ffef5e 100644 --- a/yaksh/forms.py +++ b/yaksh/forms.py @@ -1,8 +1,10 @@ from django import forms -from yaksh.models import Profile, Quiz, Question, TestCase, Course +from yaksh.models import Profile, Quiz, Question, TestCase, Course, StandardTestCase, StdoutBasedTestCase from django.contrib.auth import authenticate from django.contrib.auth.models import User +from django.contrib.contenttypes.models import ContentType + from taggit.managers import TaggableManager from taggit.forms import TagField from django.forms.models import inlineformset_factory @@ -30,8 +32,8 @@ question_types = ( test_case_types = ( ("standardtestcase", "Standard Testcase"), - # ("argument_based", "Multiple Correct Choices"), ("stdoutbasedtestcase", "Stdout Based Testcase"), + ("mcqtestcase", "MCQ Testcase"), ) UNAME_CHARS = letters + "._" + digits @@ -41,6 +43,22 @@ attempts = [(i, i) for i in range(1, 6)] attempts.append((-1, 'Infinite')) days_between_attempts = ((j, j) for j in range(401)) +def get_object_form(model, exclude_fields=None): + ctype = ContentType.objects.get(app_label="yaksh", model=model) + # ctype = ContentType.objects.get(pk=type_id) + model_class = ctype.model_class() + class _ObjectForm(forms.ModelForm): + # def __init__(self, *args, **kwargs): + # if "question" in kwargs: + # question = kwargs.pop("question") + # else: + # question = None + # self.fields["question"] = question + class Meta: + model = model_class + exclude = exclude_fields + return _ObjectForm + class UserRegisterForm(forms.Form): """A Class to create new form for User's Registration. diff --git a/yaksh/models.py b/yaksh/models.py index fd60036..b1a53f0 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -6,6 +6,7 @@ from collections import Counter from django.db import models from django.contrib.auth.models import User from django.forms.models import model_to_dict +from django.contrib.contenttypes.models import ContentType from taggit.managers import TaggableManager @@ -34,7 +35,7 @@ enrollment_methods = ( test_case_types = ( ("standardtestcase", "Standard Testcase"), ("stdoutbasedtestcase", "Stdout Based Testcase"), - # ("mcqtestcase", "MCQ Testcase"), + ("mcqtestcase", "MCQ Testcase"), ) attempts = [(i, i) for i in range(1, 6)] @@ -226,11 +227,17 @@ class Question(models.Model): question_data = {} test_case_data = [] - test_cases = self.testcase_set.all() + test_cases = self.get_test_cases() + for test in test_cases: - test_case_child_instance = test.get_child_instance(self.test_case_type) - test_case_instance_dict = test_case_child_instance.get_instance_as_dict() - test_case_data.append(test_case_field_value) + test_case_as_dict = test.get_field_value() + test_case_data.append(test_case_as_dict) + + # test_cases = self.testcase_set.all() + # for test in test_cases: + # test_case_child_instance = test.get_child_instance(self.test_case_type) + # test_case_instance_dict = test_case_child_instance.get_instance_as_dict() + # test_case_data.append(test_case_field_value) question_data['test_case_data'] = test_case_data question_data['user_answer'] = user_answer @@ -257,6 +264,18 @@ class Question(models.Model): question['user'] = user Question.objects.get_or_create(**question) + def get_test_cases(self): + test_case_ctype = ContentType.objects.get(app_label="yaksh", model=self.test_case_type) + test_cases = test_case_ctype.get_all_objects_for_this_type(question=self) + + return test_cases + + def get_test_case(self, test_case_id): + test_case_ctype = ContentType.objects.get(app_label="yaksh", model=self.test_case_type) + test_case = test_case_ctype.get_object_for_this_type(question=self, id=test_case_id) + + return test_case + def __unicode__(self): return self.summary @@ -772,8 +791,9 @@ class AssignmentUpload(models.Model): class TestCase(models.Model): question = models.ForeignKey(Question, blank=True, null = True) - def get_child_instance(self, type): - return getattr(self, type) + # def get_child_instance(self, type): + # return getattr(self, type) + class StandardTestCase(TestCase): test_case = models.TextField(blank=True) @@ -781,6 +801,9 @@ class StandardTestCase(TestCase): def get_field_value(self): return {"test_case": self.test_case} + def __unicode__(self): + return u'Question: {0} | Test Case: {1}'.format(self.question, self.test_case) + class StdoutBasedTestCase(TestCase): expected_output = models.TextField(blank=True) @@ -788,9 +811,16 @@ class StdoutBasedTestCase(TestCase): def get_field_value(self): return {"expected_output": self.expected_output} + def __unicode__(self): + return u'Question: {0} | Exp. Output: {1}'.format(self.question, self.expected_output) + + class McqTestCase(TestCase): options = models.TextField() correct = models.BooleanField(default=False) def get_field_value(self): return {"options": self.options, "correct": self.correct} + + def __unicode__(self): + return u'Question: {0} | Correct: {1}'.format(self.question, self.correct) diff --git a/yaksh/static/yaksh/js/show_testcase.js b/yaksh/static/yaksh/js/show_testcase.js new file mode 100644 index 0000000..71be9dc --- /dev/null +++ b/yaksh/static/yaksh/js/show_testcase.js @@ -0,0 +1,24 @@ +function confirm_delete(frm) +{ + var n=0; + test_case = document.getElementsByName('test_case'); + for (var i =0;iPoints:{{ form.points }}{{ form.points.errors }} Rendered:

Description: {{ form.description}} {{form.description.errors}} - Snippet: {{ form.snippet }}{{ form.snippet.errors }} + Tags: {{ form.tags }} - Options: {{ form.options }} {{form.options.errors}} + - Reference Code Path: {{ form.ref_code_path }} {{form.ref_code_path.errors}} + test_case_type: {{ form.test_case_type }}{{ form.test_case_type.errors }}
@@ -41,7 +41,12 @@ {% endif %}
-
-
+
+ + + {% if question_id %} + + {% endif %} +
{% endblock %} diff --git a/yaksh/templates/yaksh/add_testcase.html b/yaksh/templates/yaksh/add_testcase.html index 298bd50..7e29765 100644 --- a/yaksh/templates/yaksh/add_testcase.html +++ b/yaksh/templates/yaksh/add_testcase.html @@ -1,21 +1,39 @@ {% extends "manage.html" %} - -{% block subtitle %}Add Question{% endblock %} +{% block subtitle %}Add Test Case{% endblock %} {% block css %} - {% endblock %} +{% block manage %} +
+ {% csrf_token %} +
+ + {{ form.as_table }} +
+
+ +
+
+
+{% endblock %} + + diff --git a/yaksh/templates/yaksh/show_testcase.html b/yaksh/templates/yaksh/show_testcase.html new file mode 100644 index 0000000..b9cb55f --- /dev/null +++ b/yaksh/templates/yaksh/show_testcase.html @@ -0,0 +1,31 @@ +{% extends "manage.html" %} + +{% block title %} Test Case List {% endblock title %} + +{% block script %} + +{% endblock %} + +{% block subtitle %} Test Case List {% endblock %} +{% block manage %} +{% if not test_cases %} +
No Test Cases Available for This Question.
+   +{% endif %} + + +{% if test_cases %} +
+{% csrf_token %} + +{% for test_case in test_cases %} +  {{ test_case }}
+{% endfor %} + +

+   + +
+{% endif %} + +{% endblock %} diff --git a/yaksh/views.py b/yaksh/views.py index c7fdc7f..5f07880 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -22,8 +22,9 @@ import json from yaksh.models import Quiz, Question, QuestionPaper, QuestionSet, Course from yaksh.models import Profile, Answer, AnswerPaper, User, TestCase from yaksh.forms import UserRegisterForm, UserLoginForm, QuizForm,\ - QuestionForm, RandomQuestionForm, TestCaseFormSet,\ - QuestionFilterForm, CourseForm, ProfileForm, UploadFileForm + QuestionForm, RandomQuestionForm,\ + QuestionFilterForm, CourseForm, ProfileForm, UploadFileForm,\ + get_object_form from yaksh.xmlrpc_clients import code_server from settings import URL_ROOT from yaksh.models import AssignmentUpload @@ -181,8 +182,9 @@ def add_question(request, question_id=None): return my_redirect("/exam/manage/questions") return my_render_to_response('yaksh/add_question.html', - {'form': form}, - # 'formset': test_case_formset}, + # {'form': form}, + {'form': form, + 'question_id': question_id}, context_instance=ci) else: d = Question.objects.get(id=question_id) @@ -192,56 +194,112 @@ def add_question(request, question_id=None): question = Question.objects.get(id=question_id) return my_redirect("/exam/manage/questions") return my_render_to_response('yaksh/add_question.html', - {'form': form}, - # 'formset': test_case_formset}, + # {'form': form}, + {'form': form, + 'question_id': question_id}, context_instance=ci) else: return my_render_to_response('yaksh/add_question.html', - {'form': form}, - # 'formset': test_case_formset}, + # {'form': form}, + {'form': form, + 'question_id': question_id}, context_instance=ci) else: if question_id is None: form = QuestionForm() # test_case_formset = TestCaseFormSet(prefix='test', instance=Question()) return my_render_to_response('yaksh/add_question.html', - {'form': form}, - # 'formset': test_case_formset}, + # {'form': form}, + {'form': form, + 'question_id': question_id}, context_instance=ci) else: d = Question.objects.get(id=question_id) form = QuestionForm(instance=d) return my_render_to_response('yaksh/add_question.html', - {'form': form}, - # 'formset': test_case_formset}, + # {'form': form}, + {'form': form, + 'question_id': question_id}, context_instance=ci) @login_required -def add_testcase(request, question_id=None): - """To add new test case for a question""" +def show_testcase(request, question_id=None): + """Show all test cases related to Questions""" + user = request.user ci = RequestContext(request) + if not user.is_authenticated() or not is_moderator(user): + raise Http404('You are not allowed to view this page!') if not question_id: raise Http404('No Question Found') + question = Question.objects.get(id=question_id) - initial = {'question': question} + test_cases = question.get_test_cases() + + if request.POST.get('delete') == 'delete': + data = request.POST.getlist('test_case') + for i in data: + for t in test_cases: + if int(i) == t.id: + test_case_deleted = t.delete() + test_cases = question.get_test_cases() + + return my_render_to_response('yaksh/show_testcase.html', + {'test_cases': test_cases, + 'question_id': question_id}, + context_instance=ci) + + +@login_required +def add_testcase(request, question_id=None, test_case_id=None): + """To add new test case for a question""" + user = request.user + ci = RequestContext(request) + if not user.is_authenticated() or not is_moderator(user): + raise Http404('You are not allowed to view this page!') + if not question_id: + raise Http404('No Question Found') + + question = Question.objects.get(id=question_id) test_case_type = question.test_case_type - if test_case_type == "standardtestcase": - from yaksh.forms import StandardTestCaseForm - if request.method == "POST": - form = StandardTestCaseForm(request.POST) - initial = {'question': question} - form = StandardTestCaseForm(initial) + if test_case_id: + instance = question.get_test_case(test_case_id) + else: + instance = None + + # test_cases = self.testcase_set.all() + # for test in test_cases: + # test_case_child_instance = test.get_child_instance(test_case_type) + + test_case_form_object = get_object_form(model=test_case_type, exclude_fields=['question']) + + # if test_case_type == "standardtestcase": + # from yaksh.forms import StandardTestCaseForm + # if request.method == "POST": + # form = StandardTestCaseForm(request.POST) + # form = StandardTestCaseForm(initial) if request.method == "POST": + form = test_case_form_object(request.POST, instance=instance) if form.is_valid(): - form.save() + form_data = form.save(commit=False) + form_data.question = question + form_data.save() + return my_redirect("/exam/manage/showtestcase/{0}".format(question_id)) + else: + return my_render_to_response('yaksh/add_testcase.html', + {'form': form, + 'question_id': question_id}, + context_instance=ci) + else: + form = test_case_form_object(initial={"question": question}, instance=instance) return my_render_to_response('yaksh/add_testcase.html', - {'form': form}, + {'form': form, + 'question_id': question_id}, context_instance=ci) @login_required -- cgit