From 8e2469e937fd4f80ebf2053d6e21c9b670d38ea2 Mon Sep 17 00:00:00 2001 From: ankitjavalkar Date: Fri, 20 Feb 2015 18:04:36 +0530 Subject: Modify form, views and templates to reflect changes made to TestCase model --- testapp/exam/forms.py | 27 +++-- testapp/exam/models.py | 16 +-- testapp/exam/templates/exam/add_question.html | 37 +++++-- testapp/exam/templates/exam/edit_question.html | 34 ++++++- testapp/exam/views.py | 135 ++++++++++++++++++------- 5 files changed, 188 insertions(+), 61 deletions(-) diff --git a/testapp/exam/forms.py b/testapp/exam/forms.py index 1f12a3b..e3cef40 100644 --- a/testapp/exam/forms.py +++ b/testapp/exam/forms.py @@ -1,5 +1,5 @@ from django import forms -from testapp.exam.models import Profile, Quiz, Question +from exam.models import Profile, Quiz, Question, TestCase from django.contrib.auth import authenticate from django.contrib.auth.models import User @@ -8,6 +8,7 @@ from taggit.forms import TagField from taggit_autocomplete_modified.managers import TaggableManagerAutocomplete from taggit_autocomplete_modified.widgets import TagAutocomplete from taggit_autocomplete_modified import settings +from django.forms.models import inlineformset_factory from string import letters, punctuation, digits import datetime @@ -177,7 +178,7 @@ class QuizForm(forms.Form): new_quiz.save() -class QuestionForm(forms.Form): +class QuestionForm(forms.ModelForm): """Creates a form to add or edit a Question. It has the related fields and functions required.""" @@ -186,8 +187,8 @@ class QuestionForm(forms.Form): description = forms.CharField(widget=forms.Textarea\ (attrs={'cols': 40, 'rows': 1})) points = forms.FloatField() - test = forms.CharField(widget=forms.Textarea\ - (attrs={'cols': 40, 'rows': 1})) + # test = forms.CharField(widget=forms.Textarea\ + # (attrs={'cols': 40, 'rows': 1}), required=False) options = forms.CharField(widget=forms.Textarea\ (attrs={'cols': 40, 'rows': 1}), required=False) language = forms.CharField(max_length=20, widget=forms.Select\ @@ -199,11 +200,11 @@ class QuestionForm(forms.Form): snippet = forms.CharField(widget=forms.Textarea\ (attrs={'cols': 40, 'rows': 1}), required=False) - def save(self): + def save(self, commit=True): summary = self.cleaned_data["summary"] description = self.cleaned_data["description"] points = self.cleaned_data['points'] - test = self.cleaned_data["test"] + # test = self.cleaned_data["test"] options = self.cleaned_data['options'] language = self.cleaned_data['language'] type = self.cleaned_data["type"] @@ -214,13 +215,20 @@ class QuestionForm(forms.Form): new_question.summary = summary new_question.description = description new_question.points = points - new_question.test = test + # new_question.test = test new_question.options = options new_question.language = language new_question.type = type new_question.active = active new_question.snippet = snippet - new_question.save() + new_question = super(QuestionForm, self).save(commit=False) + if commit: + new_question.save() + + return new_question + + class Meta: + model = Question class RandomQuestionForm(forms.Form): @@ -229,3 +237,6 @@ class RandomQuestionForm(forms.Form): marks = forms.CharField(max_length=8, widget=forms.Select\ (choices=(('select', 'Select Marks'),))) shuffle_questions = forms.BooleanField(required=False) + +TestCaseFormSet = inlineformset_factory(Question, TestCase,\ + can_order=False, can_delete=False, extra=1) diff --git a/testapp/exam/models.py b/testapp/exam/models.py index 4b8f737..ea79ad2 100644 --- a/testapp/exam/models.py +++ b/testapp/exam/models.py @@ -59,8 +59,8 @@ class Question(models.Model): # Number of points for the question. points = models.FloatField(default=1.0) - # Test cases for the question in the form of code that is run. - test = models.TextField(blank=True) + # # Test cases for the question in the form of code that is run. + # test = models.TextField(blank=True) # Any multiple choice options. Place one option per line. options = models.TextField(blank=True) @@ -429,19 +429,19 @@ class AssignmentUpload(models.Model): ################################################################################ class TestCase(models.Model): - question = models.ForeignKey(Question) + question = models.ForeignKey(Question, blank=True, null = True) # Test case function name - func_name = models.CharField(max_length=200) + func_name = models.CharField(blank=True, null = True, max_length=200) # Test case Keyword arguments in dict form - kw_args = models.TextField(blank=True) + kw_args = models.TextField(blank=True, null = True) # Test case Positional arguments in list form - pos_args = models.TextField(blank=True) + pos_args = models.TextField(blank=True, null = True) # Test case Expected answer in list form - expected_answer = models.TextField(blank=True) + expected_answer = models.TextField(blank=True, null = True) # Test case path to system test code applicable for CPP, C, Java and Scilab - ref_code_path = models.TextField(blank=True) + ref_code_path = models.TextField(blank=True, null = True) diff --git a/testapp/exam/templates/exam/add_question.html b/testapp/exam/templates/exam/add_question.html index b6ce908..d989b81 100644 --- a/testapp/exam/templates/exam/add_question.html +++ b/testapp/exam/templates/exam/add_question.html @@ -27,17 +27,38 @@ Points:{{ form.points }}{{ form.points.errors }} Rendered:

Description: {{ form.description}} {{form.description.errors}} - Test: {{ form.test }}{{form.test.errors}} - Test Keyword Arguments: {{ form.test_keyword_args }}{{form.test.errors}} - Test Positional Arguments: {{ form.test_pos_args }}{{form.test.errors}} - Test Expected Answer: {{ form.test_expected_answer }}{{form.test.errors}} + Snippet: {{ form.snippet }}{{ form.snippet.errors }} Tags: {{ form.tags }} - Options: {{ form.options }} {{form.options.errors}} - - + Options: {{ form.options }} {{form.options.errors}} + +
+ {% if formset%} + {{ formset.management_form }} + {% for form in formset %} + {{ form }} + {% endfor %} + {% endif %} +
+ + -
+
+ +

+
{% endblock %} diff --git a/testapp/exam/templates/exam/edit_question.html b/testapp/exam/templates/exam/edit_question.html index b28cc3e..1c34dee 100644 --- a/testapp/exam/templates/exam/edit_question.html +++ b/testapp/exam/templates/exam/edit_question.html @@ -21,7 +21,7 @@ - {% for form in forms %} + + + {% for question, test in data_list %} + +
{{question.summary.value}} + + + {% endfor %}
+ + {% for i in data %} {% endfor %} diff --git a/testapp/exam/views.py b/testapp/exam/views.py index be0d292..3d22d55 100644 --- a/testapp/exam/views.py +++ b/testapp/exam/views.py @@ -18,8 +18,8 @@ from itertools import chain from testapp.exam.models import Quiz, Question, QuestionPaper, QuestionSet from testapp.exam.models import Profile, Answer, AnswerPaper, User, TestCase from testapp.exam.forms import UserRegisterForm, UserLoginForm, QuizForm,\ - QuestionForm, RandomQuestionForm -from testapp.exam.xmlrpc_clients import code_server + QuestionForm, RandomQuestionForm, TestCaseFormSet +from exam.xmlrpc_clients import code_server from settings import URL_ROOT from testapp.exam.models import AssignmentUpload @@ -281,7 +281,7 @@ def edit_quiz(request): def edit_question(request): - """Edit the list of questions seleted by the user for editing.""" + """Edit the list of questions selected by the user for editing.""" user = request.user if not user.is_authenticated() or not is_moderator(user): raise Http404('You are not allowed to view this page!') @@ -290,7 +290,6 @@ def edit_question(request): summary = request.POST.getlist('summary') description = request.POST.getlist('description') points = request.POST.getlist('points') - test = request.POST.getlist('test') options = request.POST.getlist('options') type = request.POST.getlist('type') active = request.POST.getlist('active') @@ -298,10 +297,15 @@ def edit_question(request): snippet = request.POST.getlist('snippet') for j, question_id in enumerate(question_list): question = Question.objects.get(id=question_id) + test_case_formset = TestCaseFormSet(request.POST, prefix='test', instance=question) + if test_case_formset.is_valid(): + test_case_instance = test_case_formset.save(commit=False) + for i in test_case_instance: + i.save() + question.summary = summary[j] question.description = description[j] question.points = points[j] - question.test = test[j] question.options = options[j] question.active = active[j] question.language = language[j] @@ -314,6 +318,16 @@ def edit_question(request): def add_question(request, question_id=None): """To add a new question in the database. Create a new question and store it.""" + + def add_or_delete_test_form(post_request, instance): + request_copy = post_request.copy() + if 'add_test' in post_request: + request_copy['test-TOTAL_FORMS'] = int(request_copy['test-TOTAL_FORMS']) + 1 + elif 'delete_test' in post_request: + request_copy['test-TOTAL_FORMS'] = int(request_copy['test-TOTAL_FORMS']) - 1 + test_case_formset = TestCaseFormSet(request_copy, prefix='test', instance=instance) + return test_case_formset + user = request.user ci = RequestContext(request) if not user.is_authenticated() or not is_moderator(user): @@ -321,44 +335,84 @@ def add_question(request, question_id=None): if request.method == "POST": form = QuestionForm(request.POST) if form.is_valid(): - data = form.cleaned_data if question_id is None: - form.save() - question = Question.objects.order_by("-id")[0] - tags = form['tags'].data.split(',') - for i in range(0, len(tags)-1): - tag = tags[i].strip() - question.tags.add(tag) - return my_redirect("/exam/manage/questions") + test_case_formset = add_or_delete_test_form(request.POST, form.save(commit=False)) + if 'save_question' in request.POST: + qtn = form.save(commit=False) + test_case_formset = TestCaseFormSet(request.POST, prefix='test', instance=qtn) + form.save() + question = Question.objects.order_by("-id")[0] + tags = form['tags'].data.split(',') + for i in range(0, len(tags)-1): + tag = tags[i].strip() + question.tags.add(tag) + if test_case_formset.is_valid(): + test_case_formset.save() + else: + return my_render_to_response('exam/add_question.html', + {'form': form, + 'formset': test_case_formset}, + context_instance=ci) + + return my_redirect("/exam/manage/questions") + + return my_render_to_response('exam/add_question.html', + {'form': form, + 'formset': test_case_formset}, + context_instance=ci) + else: d = Question.objects.get(id=question_id) - d.summary = form['summary'].data - d.description = form['description'].data - d.points = form['points'].data - d.test = form['test'].data - d.options = form['options'].data - d.type = form['type'].data - d.active = form['active'].data - d.language = form['language'].data - d.snippet = form['snippet'].data - d.save() - question = Question.objects.get(id=question_id) - for tag in question.tags.all(): - question.tags.remove(tag) - tags = form['tags'].data.split(',') - for i in range(0, len(tags)-1): - tag = tags[i].strip() - question.tags.add(tag) - return my_redirect("/exam/manage/questions") + test_case_formset = add_or_delete_test_form(request.POST, d) + if 'save_question' in request.POST: + d.summary = form['summary'].data + d.description = form['description'].data + d.points = form['points'].data + d.options = form['options'].data + d.type = form['type'].data + d.active = form['active'].data + d.language = form['language'].data + d.snippet = form['snippet'].data + d.save() + question = Question.objects.get(id=question_id) + for tag in question.tags.all(): + question.tags.remove(tag) + tags = form['tags'].data.split(',') + for i in range(0, len(tags)-1): + tag = tags[i].strip() + question.tags.add(tag) + + test_case_formset = TestCaseFormSet(request.POST, prefix='test', instance=question) + if test_case_formset.is_valid(): + test_case_instance = test_case_formset.save(commit=False) + for i in test_case_instance: + i.save() + else: + return my_render_to_response('exam/add_question.html', + {'form': form, + 'formset': test_case_formset}, + context_instance=ci) + + + return my_redirect("/exam/manage/questions") + return my_render_to_response('exam/add_question.html', + {'form': form, + 'formset': test_case_formset}, + context_instance=ci) + else: return my_render_to_response('exam/add_question.html', {'form': form}, context_instance=ci) else: + form = QuestionForm() + test_case_formset = TestCaseFormSet(prefix='test', instance=Question()) if question_id is None: form = QuestionForm() + test_case_formset = TestCaseFormSet(prefix='test', instance=Question()) return my_render_to_response('exam/add_question.html', - {'form': form}, + {'form': form, + 'formset': test_case_formset}, context_instance=ci) else: d = Question.objects.get(id=question_id) @@ -366,7 +420,6 @@ def add_question(request, question_id=None): form.initial['summary'] = d.summary form.initial['description'] = d.description form.initial['points'] = d.points - form.initial['test'] = d.test form.initial['options'] = d.options form.initial['type'] = d.type form.initial['active'] = d.active @@ -380,8 +433,13 @@ def add_question(request, question_id=None): if (initial_tags == ","): initial_tags = "" form.initial['tags'] = initial_tags + + test_case_formset = TestCaseFormSet(prefix='test', + instance=d) + return my_render_to_response('exam/add_question.html', - {'form': form}, + {'form': form, + 'formset': test_case_formset}, context_instance=ci) @@ -1172,13 +1230,13 @@ def show_all_questions(request): data = request.POST.getlist('question') forms = [] + formsets = [] for j in data: d = Question.objects.get(id=j) form = QuestionForm() form.initial['summary'] = d.summary form.initial['description'] = d.description form.initial['points'] = d.points - form.initial['test'] = d.test form.initial['options'] = d.options form.initial['type'] = d.type form.initial['active'] = d.active @@ -1193,8 +1251,13 @@ def show_all_questions(request): initial_tags = "" form.initial['tags'] = initial_tags forms.append(form) + test_case_formset = TestCaseFormSet(prefix='test', instance=d) + formsets.append(test_case_formset) + data_list = zip(forms, formsets) + return my_render_to_response('exam/edit_question.html', - {'forms': forms, 'data': data}, + {'data': data, + 'data_list': data_list}, context_instance=ci) else: questions = Question.objects.all() -- cgit