diff options
author | Prabhu Ramachandran | 2016-12-19 22:56:28 +0530 |
---|---|---|
committer | GitHub | 2016-12-19 22:56:28 +0530 |
commit | 1400eeb1d5af1cd1d69e015a19a319ab35d357c4 (patch) | |
tree | 1fcd565a5bf35eefadc5e5f55cf2f113e3796b66 | |
parent | f416da9901ebca437c100bb80511eb87544f709d (diff) | |
parent | d81919b6c8418da9bed0a78f5a7d5344f0ccbc16 (diff) | |
download | online_test-1400eeb1d5af1cd1d69e015a19a319ab35d357c4.tar.gz online_test-1400eeb1d5af1cd1d69e015a19a319ab35d357c4.tar.bz2 online_test-1400eeb1d5af1cd1d69e015a19a319ab35d357c4.zip |
Merge pull request #162 from prathamesh920/question-form-interface
Question form interface
-rw-r--r-- | yaksh/models.py | 19 | ||||
-rw-r--r-- | yaksh/templates/yaksh/add_question.html | 45 | ||||
-rw-r--r-- | yaksh/test_models.py | 4 | ||||
-rw-r--r-- | yaksh/urls.py | 2 | ||||
-rw-r--r-- | yaksh/views.py | 127 |
5 files changed, 89 insertions, 108 deletions
diff --git a/yaksh/models.py b/yaksh/models.py index dc12707..7fae305 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -53,6 +53,7 @@ test_case_types = ( ("standardtestcase", "Standard Testcase"), ("stdiobasedtestcase", "StdIO Based Testcase"), ("mcqtestcase", "MCQ Testcase"), + ("hooktestcase", "Hook Testcase"), ) attempts = [(i, i) for i in range(1, 6)] @@ -1129,10 +1130,11 @@ class AssignmentUpload(models.Model): ################################################################################ class TestCase(models.Model): question = models.ForeignKey(Question, blank=True, null = True) + type = models.CharField(max_length=24, choices=test_case_types, null=True) class StandardTestCase(TestCase): - test_case = models.TextField(blank=True) - weight = models.FloatField(default=0.0) + test_case = models.TextField() + weight = models.FloatField(default=1.0) def get_field_value(self): return {"test_case": self.test_case, @@ -1145,9 +1147,9 @@ class StandardTestCase(TestCase): class StdioBasedTestCase(TestCase): - expected_input = models.TextField(blank=True) - expected_output = models.TextField() - weight = models.IntegerField(default=0.0) + expected_input = models.CharField(max_length=100, blank=True) + expected_output = models.CharField(max_length=100) + weight = models.IntegerField(default=1.0) def get_field_value(self): return {"expected_output": self.expected_output, @@ -1161,7 +1163,7 @@ class StdioBasedTestCase(TestCase): class McqTestCase(TestCase): - options = models.TextField() + options = models.CharField(max_length=100) correct = models.BooleanField(default=False) def get_field_value(self): @@ -1171,3 +1173,8 @@ class McqTestCase(TestCase): return u'Question: {0} | Correct: {1}'.format(self.question, self.correct ) + + +class HookTestCase(TestCase): + code = models.TextField() + weight = models.FloatField(default=1.0) diff --git a/yaksh/templates/yaksh/add_question.html b/yaksh/templates/yaksh/add_question.html index e1b05fe..57e5e78 100644 --- a/yaksh/templates/yaksh/add_question.html +++ b/yaksh/templates/yaksh/add_question.html @@ -13,20 +13,20 @@ {% block onload %} onload='javascript:textareaformat();' {% endblock %} {% block content %} -<form action="" method="post" name=frm onSubmit="return autosubmit();" enctype="multipart/form-data"> +<form action="{{ URL_ROOT }}/exam/manage/addquestion/{{ question.id }}/" method="post" name=frm onSubmit="return autosubmit();" enctype="multipart/form-data"> {% csrf_token %} <center><table class="table"> - <tr><td>Summary: <td>{{ form.summary }}{{ form.summary.errors }} - <tr><td> Language: <td> {{form.language}}{{form.language.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>Summary: <td>{{ qform.summary }}{{ qform.summary.errors }} + <tr><td> Language: <td> {{qform.language}}{{qform.language.errors}} + <tr><td> Type: <td> {{ qform.type }}{{qform.type.errors}} + <tr><td>Points:<td><button class="btn-mini" type="button" onClick="increase(frm);">+</button>{{qform.points }}<button class="btn-mini" type="button" onClick="decrease(frm);">-</button>{{ qform.points.errors }} <tr><td><strong>Rendered: </strong><td><p id='my'></p> - <tr><td>Description: <td>{{ form.description}} {{form.description.errors}} - <tr><td>Tags: <td>{{ form.tags }} - <tr><td>Snippet: <td>{{ form.snippet }} - <tr><td>Partial Grading: <td>{{ form.partial_grading }} - <tr><td> Test Case Type: <td> {{ form.test_case_type }}{{ form.test_case_type.errors }} - <tr><td> File: <td> {{ upload_form.file_field }}{{ upload_form.file_field.errors }} + <tr><td>Description: <td>{{ qform.description}} {{qform.description.errors}} + <tr><td>Tags: <td>{{ qform.tags }} + <tr><td>Snippet: <td>{{ qform.snippet }} + <tr><td>Partial Grading: <td>{{ qform.partial_grading }} + <tr><td> Test Case Type: <td> {{ qform.test_case_type }}{{ qform.test_case_type.errors }} + <tr><td> File: <td> {{ fileform.file_field }}{{ fileform.file_field.errors }} {% if uploaded_files %}<br><b>Uploaded files:</b><br>Check on delete to delete files, extract to extract files and hide to hide files from student(if required)<br> {% for file in uploaded_files %} @@ -36,22 +36,29 @@ <input type="checkbox" name="hide" value="{{file.id}}" >{% if file.hide %} show{% else %} hide{% endif %}</input><br> <a href="{{file.file.url}}">{{ file.file.name }}</a> - <br> {% endfor %}{% endif %} + </table></center> + {% for formset in formsets %} <div class="form-group"> - {{ test_case_formset.management_form }} + {{ formset.management_form }} - {% for form in test_case_formset %} - <div class="link-formset"> - {{ form }} + {% for form in formset %} + <div class="link-formset well"> + {{ form.as_p }} </div> {% endfor %} </div> - - </table></center> + {% endfor %} + <p><label for="case_type">Add Test Case:</label> <select id="case_type" name="case_type" onchange="frm.submit()"> + <option value="" selected="selected">---------</option> + <option value="standardtestcase">Standard </option> + <option value="stdiobasedtestcase">StdIO </option> + <option value="mcqtestcase">MCQ/MCC </option> + <option value="hooktestcase">Hook </option> + </select></p> <center> - <button class="btn" type="submit" name="save_question">Save & Add Testcase</button> + <button class="btn" type="submit" name="save_question">Save</button> <button class="btn" type="button" name="button" onClick='location.replace("{{URL_ROOT}}/exam/manage/questions/");'>Back to Questions</button> <button class="btn" type="submit" name="delete_files">Delete Selected Files</button> </center> diff --git a/yaksh/test_models.py b/yaksh/test_models.py index 1aeffb6..522da89 100644 --- a/yaksh/test_models.py +++ b/yaksh/test_models.py @@ -142,7 +142,7 @@ class QuestionTestCases(unittest.TestCase): self.upload_test_case.save() self.user_answer = "demo_answer" self.test_case_upload_data = [{"test_case": "assert fact(3)==6", - "weight": 0.0 + "weight": 1.0 }] questions_data = [{"snippet": "def fact()", "active": True, "points": 1.0, @@ -881,7 +881,7 @@ class TestCaseTestCases(unittest.TestCase): answer_data = {"user_answer": "demo_answer", "test_case_data": [ {"test_case": "assert myfunc(12, 13) == 15", - "weight": 0.0 + "weight": 1.0 } ] } diff --git a/yaksh/urls.py b/yaksh/urls.py index bb8cf2e..036c6a3 100644 --- a/yaksh/urls.py +++ b/yaksh/urls.py @@ -52,7 +52,7 @@ urlpatterns += [ url(r'^view_answerpaper/(?P<questionpaper_id>\d+)/$', views.view_answerpaper, name='view_answerpaper'), url(r'^manage/$', views.prof_manage, name='manage'), url(r'^manage/addquestion/$', views.add_question), - url(r'^manage/addquestion/(?P<question_id>\d+)/$', views.edit_question), + url(r'^manage/addquestion/(?P<question_id>\d+)/$', views.add_question), url(r'^manage/addquiz/(?P<course_id>\d+)/$', views.add_quiz, name='add_quiz'), url(r'^manage/addquiz/(?P<course_id>\d+)/(?P<quiz_id>\d+)/$', views.add_quiz, name='edit_quiz'), url(r'^manage/gradeuser/$', views.grade_user), diff --git a/yaksh/views.py b/yaksh/views.py index b6cf578..0d77426 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -25,7 +25,7 @@ import six # Local imports. from yaksh.models import get_model_class, Quiz, Question, QuestionPaper, QuestionSet, Course from yaksh.models import Profile, Answer, AnswerPaper, User, TestCase, FileUpload,\ - has_profile + has_profile, StandardTestCase, McqTestCase, StdioBasedTestCase, HookTestCase from yaksh.forms import UserRegisterForm, UserLoginForm, QuizForm,\ QuestionForm, RandomQuestionForm,\ QuestionFilterForm, CourseForm, ProfileForm, UploadFileForm,\ @@ -130,62 +130,33 @@ def results_user(request): @login_required -def add_question(request): - """To add a new question in the database. - Create a new question and store it.""" +def add_question(request, question_id=None): user = request.user ci = RequestContext(request) + test_case_type = None - if request.method == "POST" and 'save_question' in request.POST: - question_form = QuestionForm(request.POST) - form = FileForm(request.POST, request.FILES) - if question_form.is_valid(): - new_question = question_form.save(commit=False) - new_question.user = user - new_question.save() - files = request.FILES.getlist('file_field') - if files: - for file in files: - FileUpload.objects.get_or_create(question=new_question, file=file) - return my_redirect("/exam/manage/addquestion/{0}".format(new_question.id)) - else: - return my_render_to_response('yaksh/add_question.html', - {'form': question_form, - 'upload_form': form}, - context_instance=ci) + if question_id is None: + question = Question(user=user) + question.save() else: - question_form = QuestionForm() - form = FileForm() - return my_render_to_response('yaksh/add_question.html', - {'form': question_form, - 'upload_form': form}, - context_instance=ci) - -@login_required -def edit_question(request, question_id=None): - """To add a new question in the database. - Create a new question and store it.""" - user = request.user - ci = RequestContext(request) - if not question_id: - raise Http404('No Question Found') + question = Question.objects.get(id=question_id) - question_instance = 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() - if request.method == "POST" and 'save_question' in request.POST: - question_form = QuestionForm(request.POST, instance=question_instance) - form = FileForm(request.POST, request.FILES) + + if request.method == 'POST': + qform = QuestionForm(request.POST, instance=question) + fileform = FileForm(request.POST, request.FILES) 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_instance, file=file) + FileUpload.objects.get_or_create(question=question, file=file) if extract_files_id: files = FileUpload.objects.filter(id__in=extract_files_id) for file in files: @@ -194,47 +165,43 @@ def edit_question(request, question_id=None): files = FileUpload.objects.filter(id__in=hide_files_id) for file in files: file.toggle_hide_status() - if question_form.is_valid(): - new_question = question_form.save(commit=False) - test_case_type = question_form.cleaned_data.get('test_case_type') - test_case_form_class = get_object_form(model=test_case_type, exclude_fields=['question']) - test_case_model_class = get_model_class(test_case_type) - TestCaseInlineFormSet = inlineformset_factory(Question, test_case_model_class, form=test_case_form_class, extra=1) - test_case_formset = TestCaseInlineFormSet(request.POST, request.FILES, instance=new_question) - if test_case_formset.is_valid(): - new_question.save() - test_case_formset.save() - return my_redirect("/exam/manage/addquestion/{0}".format(new_question.id)) + formsets = [] + for testcase in TestCase.__subclasses__(): + formset = inlineformset_factory(Question, testcase, extra=0, + fields='__all__') + 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 + question.save() + for formset in formsets: + if formset.is_valid(): + formset.save() + test_case_type = request.POST.get('case_type', None) else: - test_case_type = question_form.cleaned_data.get('test_case_type') - test_case_form_class = get_object_form(model=test_case_type, exclude_fields=['question']) - test_case_model_class = get_model_class(test_case_type) - TestCaseInlineFormSet = inlineformset_factory(Question, test_case_model_class, form=test_case_form_class, extra=1) - test_case_formset = TestCaseInlineFormSet(request.POST, request.FILES, instance=question_instance) - uploaded_files = FileUpload.objects.filter(question_id=question_instance.id) - return my_render_to_response('yaksh/add_question.html', - {'form': question_form, - 'test_case_formset': test_case_formset, - 'question_id': question_id, - 'upload_form': form, - 'uploaded_files': uploaded_files}, + context = {'qform': qform, 'fileform': fileform, 'question': question, + 'formsets': formsets, 'uploaded_files': uploaded_files} + return my_render_to_response("yaksh/add_question.html", context, context_instance=ci) - else: - question_form = QuestionForm(instance=question_instance) - form = FileForm() - test_case_type = question_instance.test_case_type - test_case_form_class = get_object_form(model=test_case_type, exclude_fields=['question']) - test_case_model_class = get_model_class(test_case_type) - TestCaseInlineFormSet = inlineformset_factory(Question, test_case_model_class, form=test_case_form_class, extra=1) - test_case_formset = TestCaseInlineFormSet(instance=question_instance) - uploaded_files = FileUpload.objects.filter(question_id=question_instance.id) - return my_render_to_response('yaksh/add_question.html', - {'form': question_form, - 'test_case_formset': test_case_formset, - 'question_id': question_id, - 'upload_form': form, - 'uploaded_files': uploaded_files}, - context_instance=ci) + + 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__') + else: + formset = inlineformset_factory(Question, testcase, extra=0, + fields='__all__') + formsets.append(formset(instance=question)) + context = {'qform': qform, 'fileform': fileform, 'question': question, + 'formsets': formsets, 'uploaded_files': uploaded_files} + return my_render_to_response("yaksh/add_question.html", context, context_instance=ci) + @login_required def add_quiz(request, course_id, quiz_id=None): |