diff options
author | King | 2016-05-05 18:46:19 +0530 |
---|---|---|
committer | King | 2016-05-05 18:46:19 +0530 |
commit | d386d24aaa662f91e4314060926dc9bc02426c7d (patch) | |
tree | 28e8b0d3e39cf5d9a6ce77b42b712290f1a3baf3 | |
parent | 8841e5ed4f8f79b7067ddb3523f4a3ec50f362b3 (diff) | |
parent | e81b13f7d94c0877801726fc85e967f36ba8bd90 (diff) | |
download | online_test-d386d24aaa662f91e4314060926dc9bc02426c7d.tar.gz online_test-d386d24aaa662f91e4314060926dc9bc02426c7d.tar.bz2 online_test-d386d24aaa662f91e4314060926dc9bc02426c7d.zip |
Merge pull request #93 from adityacp/load_dump_questions
Load dump questions
-rw-r--r-- | yaksh/forms.py | 11 | ||||
-rw-r--r-- | yaksh/models.py | 25 | ||||
-rw-r--r-- | yaksh/templates/yaksh/ajax_question_filter.html | 3 | ||||
-rw-r--r-- | yaksh/templates/yaksh/showquestions.html | 22 | ||||
-rw-r--r-- | yaksh/tests.py | 77 | ||||
-rw-r--r-- | yaksh/urls.py | 6 | ||||
-rw-r--r-- | yaksh/views.py | 67 |
7 files changed, 170 insertions, 41 deletions
diff --git a/yaksh/forms.py b/yaksh/forms.py index 16f82fb..c5bec4c 100644 --- a/yaksh/forms.py +++ b/yaksh/forms.py @@ -152,7 +152,7 @@ class QuestionForm(forms.ModelForm): class Meta: model = Question - fields = '__all__' + exclude = ['user'] class RandomQuestionForm(forms.Form): @@ -165,8 +165,9 @@ class RandomQuestionForm(forms.Form): class QuestionFilterForm(forms.Form): def __init__(self, *args, **kwargs): + user = kwargs.pop("user") super(QuestionFilterForm, self).__init__(*args, **kwargs) - questions = Question.objects.all() + questions = Question.objects.filter(user_id=user.id) points_list = questions.values_list('points', flat=True).distinct() points_options = [('select', 'Select Marks')] points_options.extend([(point, point) for point in points_list]) @@ -188,6 +189,7 @@ class CourseForm(forms.ModelForm): model = Course fields = ['name', 'active', 'enrollment'] + class ProfileForm(forms.ModelForm): """ profile form for students and moderators """ @@ -205,3 +207,8 @@ class ProfileForm(forms.ModelForm): super(ProfileForm, self).__init__(*args, **kwargs) self.fields['first_name'].initial = user.first_name self.fields['last_name'].initial = user.last_name + + +class UploadFileForm(forms.Form): + file = forms.FileField() + diff --git a/yaksh/models.py b/yaksh/models.py index 561b334..6e59d7a 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -173,6 +173,9 @@ class Question(models.Model): # Tags for the Question. tags = TaggableManager(blank=True) + # user for particular question + user = models.ForeignKey(User, related_name="user") + def consolidate_answer_data(self, test_cases, user_answer): test_case_data_dict = [] question_info_dict = {} @@ -208,6 +211,26 @@ class Question(models.Model): return json.dumps(question_info_dict) + def dump_into_json(self, question_ids, user): + questions = Question.objects.filter(id__in = question_ids, user_id = user.id) + questions_dict = [] + for question in questions: + q_dict = {'summary': question.summary, 'description': question.description, + 'points': question.points, 'test': question.test, + 'ref_code_path': question.ref_code_path, + 'options': question.options, 'language': question.language, + 'type': question.type, 'active': question.active, + 'snippet': question.snippet} + questions_dict.append(q_dict) + + return json.dumps(questions_dict, indent=2) + + def load_from_json(self, questions_list, user): + questions = json.loads(questions_list) + for question in questions: + question['user'] = user + Question.objects.get_or_create(**question) + def __unicode__(self): return self.summary @@ -487,7 +510,7 @@ class AnswerPaperManager(models.Manager): return answerpapers.values_list('user', flat=True).distinct() def get_latest_attempts(self, questionpaper_id): - papers = self.get_answerpapers_for_quiz(questionpaper_id) + papers = self._get_answerpapers_for_quiz(questionpaper_id) users = self._get_answerpapers_users(papers) latest_attempts = [] for user in users: diff --git a/yaksh/templates/yaksh/ajax_question_filter.html b/yaksh/templates/yaksh/ajax_question_filter.html index 11bf660..a63354c 100644 --- a/yaksh/templates/yaksh/ajax_question_filter.html +++ b/yaksh/templates/yaksh/ajax_question_filter.html @@ -7,7 +7,8 @@ {% for question in questions %} <li> <label> - <input type="checkbox" name="question" data-qid="{{question.id}}"> <a href="{{URL_ROOT}}/exam/manage/addquestion/{{ question.id }}">{{ question }}</a><br> + <input type="checkbox" name="question" data-qid="{{question.id}}" value= + "{{question.id}}"> <a href="{{URL_ROOT}}/exam/manage/addquestion/{{ question.id }}">{{ question }}</a><br> </label> </li> {% endfor %} diff --git a/yaksh/templates/yaksh/showquestions.html b/yaksh/templates/yaksh/showquestions.html index ca51d1a..ea42797 100644 --- a/yaksh/templates/yaksh/showquestions.html +++ b/yaksh/templates/yaksh/showquestions.html @@ -10,6 +10,19 @@ {% endblock %} {% block manage %} + +<h4>Upload json file for adding questions</h4> +<form action="" method="post" enctype="multipart/form-data"> +{% csrf_token %} +{{ upload_form.as_p }} +<button class="btn" type="submit" name="upload" value="upload">Upload File</button> +</form> +{% if message %} +<h4>{{ message }}</h4> +{% endif %} +{% if msg %} +<h4>{{ msg }}</h4> +{% endif %} <form name=frm action="" method="post"> {% csrf_token %} <div class="row" id="selectors"> @@ -31,13 +44,20 @@ </div> </div> <br> + <div id="filtered-questions"> +{% if questions %} +<h5 class="highlight"><input id="checkall" class="ignore" type="checkbox"> Select All </h5> {% for i in questions %} <input type="checkbox" name="question" value="{{ i.id }}"> <a href="{{URL_ROOT}}/exam/manage/addquestion/{{ i.id }}">{{ i }}</a><br> {% endfor %} +{% endif %} </div> <br> <button class="btn" type="button" onclick='location.replace("{{URL_ROOT}}/exam/manage/addquestion/");'>Add Question</button> -<button class="btn" type="submit" onClick="return confirm_delete(frm);" name='delete' value='delete'>Delete Selected</button> +<button class="btn" type="submit" onClick="return confirm_delete(frm);" name='delete' value='delete'>Delete Selected</button> +{% if questions %} +<button class="btn" type="submit" name='download' value='download'>Download Selected</button> +{% endif %} </form> {% endblock %} diff --git a/yaksh/tests.py b/yaksh/tests.py index d3ff4fc..58b8518 100644 --- a/yaksh/tests.py +++ b/yaksh/tests.py @@ -27,7 +27,7 @@ def setUpModule(): # create 20 questions for i in range(1, 21): - Question.objects.create(summary='Q%d' % (i), points=1, type='code') + Question.objects.create(summary='Q%d' % (i), points=1, type='code', user=user) # create a quiz quiz = Quiz.objects.create(start_date_time=datetime(2015, 10, 9, 10, 8, 15, 0), @@ -72,13 +72,22 @@ class ProfileTestCases(unittest.TestCase): class QuestionTestCases(unittest.TestCase): def setUp(self): # Single question details - self.question = Question(summary='Demo question', language='Python', + self.user1 = User.objects.get(pk=1) + self.user2 = User.objects.get(pk=2) + self.question1 = Question(summary='Demo question', language='Python', type='Code', active=True, description='Write a function', points=1.0, - snippet='def myfunc()') - self.question.save() - self.question.tags.add('python', 'function') - self.testcase = TestCase(question=self.question, + snippet='def myfunc()', user=self.user1) + self.question1.save() + + self.question2 = Question(summary='Demo Json', language='python', + type='code', active=True, + description='factorial of a no', points=2.0, + snippet='def fact()', user=self.user2) + self.question2.save() + + self.question1.tags.add('python', 'function') + self.testcase = TestCase(question=self.question1, func_name='def myfunc', kw_args='a=10,b=11', pos_args='12,13', expected_answer='15') answer_data = { "test": "", @@ -90,41 +99,73 @@ class QuestionTestCases(unittest.TestCase): "kw_args": {"a": "10", "b": "11"} }], - "id": self.question.id, + "id": self.question1.id, "ref_code_path": "", } self.answer_data_json = json.dumps(answer_data) self.user_answer = "demo_answer" + questions_data = [{"snippet": "def fact()", "active": True, "points": 1.0, + "ref_code_path": "", "description": "factorial of a no", + "language": "Python", "test": "", "type": "Code", + "options": "", "summary": "Json Demo"}] + self.json_questions_data = json.dumps(questions_data) def test_question(self): """ Test question """ - self.assertEqual(self.question.summary, 'Demo question') - self.assertEqual(self.question.language, 'Python') - self.assertEqual(self.question.type, 'Code') - self.assertFalse(self.question.options) - self.assertEqual(self.question.description, 'Write a function') - self.assertEqual(self.question.points, 1.0) - self.assertTrue(self.question.active) - self.assertEqual(self.question.snippet, 'def myfunc()') + self.assertEqual(self.question1.summary, 'Demo question') + self.assertEqual(self.question1.language, 'Python') + self.assertEqual(self.question1.type, 'Code') + self.assertFalse(self.question1.options) + self.assertEqual(self.question1.description, 'Write a function') + self.assertEqual(self.question1.points, 1.0) + self.assertTrue(self.question1.active) + self.assertEqual(self.question1.snippet, 'def myfunc()') tag_list = [] - for tag in self.question.tags.all(): + for tag in self.question1.tags.all(): tag_list.append(tag.name) self.assertEqual(tag_list, ['python', 'function']) def test_consolidate_answer_data(self): """ Test consolidate_answer_data function """ - result = self.question.consolidate_answer_data([self.testcase], + result = self.question1.consolidate_answer_data([self.testcase], self.user_answer) self.assertEqual(result, self.answer_data_json) + def test_dump_questions_into_json(self): + """ Test dump questions into json """ + question = Question() + question_id = ['24'] + questions = json.loads(question.dump_into_json(question_id, self.user1)) + for q in questions: + self.assertEqual(self.question2.summary, q['summary']) + self.assertEqual(self.question2.language, q['language']) + self.assertEqual(self.question2.type, q['type']) + self.assertEqual(self.question2.description, q['description']) + self.assertEqual(self.question2.points, q['points']) + self.assertTrue(self.question2.active) + self.assertEqual(self.question2.snippet, q['snippet']) + + def test_load_questions_from_json(self): + """ Test load questions into database from json """ + question = Question() + result = question.load_from_json(self.json_questions_data, self.user1) + question_data = Question.objects.get(pk=27) + self.assertEqual(question_data.summary, 'Json Demo') + self.assertEqual(question_data.language, 'Python') + self.assertEqual(question_data.type, 'Code') + self.assertEqual(question_data.description, 'factorial of a no') + self.assertEqual(question_data.points, 1.0) + self.assertTrue(question_data.active) + self.assertEqual(question_data.snippet, 'def fact()') ############################################################################### class TestCaseTestCases(unittest.TestCase): def setUp(self): + self.user = User.objects.get(pk=1) self.question = Question(summary='Demo question', language='Python', type='Code', active=True, description='Write a function', points=1.0, - snippet='def myfunc()') + snippet='def myfunc()', user=self.user) self.question.save() self.testcase = TestCase(question=self.question, func_name='def myfunc', kw_args='a=10,b=11', diff --git a/yaksh/urls.py b/yaksh/urls.py index b32bc36..18a64c2 100644 --- a/yaksh/urls.py +++ b/yaksh/urls.py @@ -88,5 +88,9 @@ urlpatterns += [ url(r'^manage/searchteacher/(?P<course_id>\d+)/$', views.search_teacher), url(r'^manage/addteacher/(?P<course_id>\d+)/$', views.add_teacher), url(r'^manage/allotted_course/$', views.allotted_courses), - url(r'^manage/remove_teachers/(?P<course_id>\d+)/$', views.remove_teachers) + url(r'^manage/remove_teachers/(?P<course_id>\d+)/$', views.remove_teachers), + url(r'^manage/download_questions/$', views.show_all_questions), + url(r'^manage/upload_questions/$', views.show_all_questions) ] + + diff --git a/yaksh/views.py b/yaksh/views.py index a91da29..a986d4c 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -23,7 +23,7 @@ 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 + QuestionFilterForm, CourseForm, ProfileForm, UploadFileForm from yaksh.xmlrpc_clients import code_server from settings import URL_ROOT from yaksh.models import AssignmentUpload @@ -166,6 +166,8 @@ def add_question(request, question_id=None): 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) + qtn.user = user + qtn.save() test_case_formset = TestCaseFormSet(request.POST, prefix='test', instance=qtn) form.save() question = Question.objects.order_by("-id")[0] @@ -780,7 +782,8 @@ def show_all_users(request): def ajax_questions_filter(request): """Ajax call made when filtering displayed questions.""" - filter_dict = {} + user = request.user + filter_dict = {"user_id": user.id} question_type = request.POST.get('question_type') marks = request.POST.get('marks') language = request.POST.get('language') @@ -806,21 +809,49 @@ def show_all_questions(request): user = request.user ci = RequestContext(request) - if not user.is_authenticated() or not is_moderator(user): + context = {} + if not is_moderator(user): raise Http404("You are not allowed to view this page !") - if request.method == 'POST' and request.POST.get('delete') == 'delete': - data = request.POST.getlist('question') - if data is not None: - for i in data: - question = Question.objects.get(id=i).delete() - questions = Question.objects.all() - form = QuestionFilterForm() - context = {'papers': [], - 'question': None, - 'questions': questions, - 'form': form - } + if request.method == 'POST': + if request.POST.get('delete') == 'delete': + data = request.POST.getlist('question') + if data is not None: + question = Question.objects.filter(id__in=data, user_id=user.id).delete() + + if request.POST.get('upload') == 'upload': + form = UploadFileForm(request.POST, request.FILES) + if form.is_valid(): + questions_file = request.FILES['file'] + if questions_file.name.split('.')[-1] == "json": + questions_list = questions_file.read() + question = Question() + question.load_from_json(questions_list, user) + else: + message = "Please Upload a JSON file" + context['message'] = message + + if request.POST.get('download') == 'download': + question_ids = request.POST.getlist('question') + if question_ids: + question = Question() + questions = question.dump_into_json(question_ids, user) + response = HttpResponse(questions, content_type='text/json') + response['Content-Disposition'] = 'attachment; filename=\ + "{0}_questions.json"'.format(user) + return response + else: + msg = "Please select atleast one question" + context['msg'] = msg + + questions = Question.objects.filter(user_id=user.id) + form = QuestionFilterForm(user=user) + upload_form = UploadFileForm() + context['papers'] = [] + context['question'] = None + context['questions'] = questions + context['form'] = form + context['upload_form'] = upload_form return my_render_to_response('yaksh/showquestions.html', context, context_instance=ci) @@ -944,9 +975,11 @@ 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) + 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': @@ -958,7 +991,7 @@ def ajax_questionpaper(request, query): 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)) + 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', |