From 2955c57b10c33a12b9c6def60169ee2105ca20e4 Mon Sep 17 00:00:00 2001 From: adityacp Date: Fri, 10 Mar 2017 11:10:09 +0530 Subject: Changes in models and views - Display error message if questions_dump.json is not found in zip file - Provide a sample zip file to for easy zip file creation --- yaksh/models.py | 3 +++ yaksh/views.py | 19 ++++++++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) (limited to 'yaksh') diff --git a/yaksh/models.py b/yaksh/models.py index 398f508..0a84d4e 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -402,6 +402,9 @@ class Question(models.Model): with open(json_file, 'r') as q_file: questions_list = q_file.read() self.load_questions(questions_list, user, file_path, files) + return "Questions Uploaded Successfully" + else: + return "Please upload zip file with questions_dump.json in it." def create_demo_questions(self, user): zip_file_path = os.path.join( diff --git a/yaksh/views.py b/yaksh/views.py index 63653e6..02019f4 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -20,7 +20,6 @@ import pytz from taggit.models import Tag from itertools import chain import json -import zipfile import six # Local imports. from yaksh.models import get_model_class, Quiz, Question, QuestionPaper, QuestionSet, Course @@ -31,6 +30,7 @@ from yaksh.forms import UserRegisterForm, UserLoginForm, QuizForm,\ QuestionFilterForm, CourseForm, ProfileForm, UploadFileForm,\ get_object_form, FileForm, QuestionPaperForm from .settings import URL_ROOT +from django.conf import settings from yaksh.models import AssignmentUpload from .file_utils import extract_files @@ -894,7 +894,8 @@ def show_all_questions(request): if request.POST.get('delete') == 'delete': data = request.POST.getlist('question') if data is not None: - questions = Question.objects.filter(id__in=data, user_id=user.id, active=True) + questions = Question.objects.filter(id__in=data, user_id=user.id, + active=True) for question in questions: question.active = False question.save() @@ -907,7 +908,8 @@ def show_all_questions(request): if file_name[-1] == "zip": ques = Question() files, extract_path = extract_files(questions_file) - ques.read_json(extract_path, user, files) + context['message'] = ques.read_json(extract_path, user, + files) else: message = "Please Upload a ZIP file" context['message'] = message @@ -947,6 +949,17 @@ def show_all_questions(request): return my_render_to_response('yaksh/showquestions.html', context, context_instance=ci) +@login_required +def download_demo_questions(request): + user = request.user + if not is_moderator(user): + raise Http404("You are not allowed to download!") + f_path = os.path.join(settings.FIXTURE_DIRS, "demo_questions.zip") + zip_file = open(f_path, "rb") + response = HttpResponse(zip_file, content_type='application/zip') + response['Content-Disposition'] = '''attachment;\ + filename=demo_questions.zip''' + return response @login_required def user_data(request, user_id, questionpaper_id=None): -- cgit From 2da746134de706e82f848ef975da229f9f15d64e Mon Sep 17 00:00:00 2001 From: adityacp Date: Fri, 10 Mar 2017 11:14:34 +0530 Subject: Add url to download sample zip file --- yaksh/urls.py | 1 + 1 file changed, 1 insertion(+) (limited to 'yaksh') diff --git a/yaksh/urls.py b/yaksh/urls.py index ad58985..e7a3a66 100644 --- a/yaksh/urls.py +++ b/yaksh/urls.py @@ -28,6 +28,7 @@ urlpatterns = [ url(r'^view_answerpaper/(?P\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/download_demo_question/$', views.download_demo_questions), url(r'^manage/addquestion/(?P\d+)/$', views.add_question), url(r'^manage/addquiz/(?P\d+)/$', views.add_quiz, name='add_quiz'), url(r'^manage/addquiz/(?P\d+)/(?P\d+)/$', views.add_quiz, name='edit_quiz'), -- cgit From 508a576ccfb63169c24056ded25f742bdcd186f2 Mon Sep 17 00:00:00 2001 From: adityacp Date: Fri, 10 Mar 2017 11:15:05 +0530 Subject: Add a link to download sample zip file --- yaksh/templates/yaksh/showquestions.html | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'yaksh') diff --git a/yaksh/templates/yaksh/showquestions.html b/yaksh/templates/yaksh/showquestions.html index 3668c9e..73612d5 100644 --- a/yaksh/templates/yaksh/showquestions.html +++ b/yaksh/templates/yaksh/showquestions.html @@ -10,11 +10,16 @@ {% block content %} +

Please Download Sample Zip file to view zip file contents before uploading +Questions

+Sample Zip File +

Upload ZIP file for adding questions

{% csrf_token %} {{ upload_form.as_p }} - +
{% if message %}

{{ message }}

@@ -22,6 +27,7 @@ {% if msg %}

{{ msg }}

{% endif %} +

{% csrf_token %}
-- cgit From b37244f2c6573b0f16b9dcea614400ee1ae24cf8 Mon Sep 17 00:00:00 2001 From: adityacp Date: Thu, 16 Mar 2017 16:43:12 +0530 Subject: Changes in models views and urls - Handle Json parsing error - Remove Sample file download from views and urls --- yaksh/models.py | 30 ++++++++++++++++++------------ yaksh/urls.py | 1 - yaksh/views.py | 13 ------------- 3 files changed, 18 insertions(+), 26 deletions(-) (limited to 'yaksh') diff --git a/yaksh/models.py b/yaksh/models.py index 0a84d4e..dc015d5 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -318,17 +318,19 @@ class Question(models.Model): file_names = question.pop('files') test_cases = question.pop('testcase') que, result = Question.objects.get_or_create(**question) - if file_names: - que._add_files_to_db(file_names, file_path) - for test_case in test_cases: - test_case_type = test_case.pop('test_case_type') - model_class = get_model_class(test_case_type) - new_test_case, obj_create_status = \ - model_class.objects.get_or_create( - question=que, **test_case - ) - new_test_case.type = test_case_type - new_test_case.save() + if not result: + if file_names: + que._add_files_to_db(file_names, file_path) + for test_case in test_cases: + test_case_type = test_case.pop('test_case_type') + model_class = get_model_class(test_case_type) + new_test_case, obj_create_status = \ + model_class.objects.get_or_create( + question=que, **test_case + ) + new_test_case.type = test_case_type + new_test_case.save() + if files_list: delete_files(files_list, file_path) @@ -401,7 +403,11 @@ class Question(models.Model): if os.path.exists(json_file): with open(json_file, 'r') as q_file: questions_list = q_file.read() - self.load_questions(questions_list, user, file_path, files) + try: + self.load_questions(questions_list, user, file_path, files) + except ValueError: + return "Syntax Error in Json. Please check your json file." + return "Questions Uploaded Successfully" else: return "Please upload zip file with questions_dump.json in it." diff --git a/yaksh/urls.py b/yaksh/urls.py index e7a3a66..ad58985 100644 --- a/yaksh/urls.py +++ b/yaksh/urls.py @@ -28,7 +28,6 @@ urlpatterns = [ url(r'^view_answerpaper/(?P\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/download_demo_question/$', views.download_demo_questions), url(r'^manage/addquestion/(?P\d+)/$', views.add_question), url(r'^manage/addquiz/(?P\d+)/$', views.add_quiz, name='add_quiz'), url(r'^manage/addquiz/(?P\d+)/(?P\d+)/$', views.add_quiz, name='edit_quiz'), diff --git a/yaksh/views.py b/yaksh/views.py index 02019f4..daa81eb 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -30,7 +30,6 @@ from yaksh.forms import UserRegisterForm, UserLoginForm, QuizForm,\ QuestionFilterForm, CourseForm, ProfileForm, UploadFileForm,\ get_object_form, FileForm, QuestionPaperForm from .settings import URL_ROOT -from django.conf import settings from yaksh.models import AssignmentUpload from .file_utils import extract_files @@ -949,18 +948,6 @@ def show_all_questions(request): return my_render_to_response('yaksh/showquestions.html', context, context_instance=ci) -@login_required -def download_demo_questions(request): - user = request.user - if not is_moderator(user): - raise Http404("You are not allowed to download!") - f_path = os.path.join(settings.FIXTURE_DIRS, "demo_questions.zip") - zip_file = open(f_path, "rb") - response = HttpResponse(zip_file, content_type='application/zip') - response['Content-Disposition'] = '''attachment;\ - filename=demo_questions.zip''' - return response - @login_required def user_data(request, user_id, questionpaper_id=None): """Render user data.""" -- cgit From 7d568d24514cfc67a149b1eae80ba3d8490c1016 Mon Sep 17 00:00:00 2001 From: adityacp Date: Thu, 16 Mar 2017 16:45:37 +0530 Subject: Remove link for sample download of questions upload --- yaksh/templates/yaksh/showquestions.html | 4 ---- 1 file changed, 4 deletions(-) (limited to 'yaksh') diff --git a/yaksh/templates/yaksh/showquestions.html b/yaksh/templates/yaksh/showquestions.html index 73612d5..157b378 100644 --- a/yaksh/templates/yaksh/showquestions.html +++ b/yaksh/templates/yaksh/showquestions.html @@ -10,10 +10,6 @@ {% block content %} -

Please Download Sample Zip file to view zip file contents before uploading -Questions

-Sample Zip File -

Upload ZIP file for adding questions

{% csrf_token %} -- cgit From eb3afa3b86ca7a129c9d1365e0ae7946b0c25d32 Mon Sep 17 00:00:00 2001 From: adityacp Date: Thu, 16 Mar 2017 16:46:29 +0530 Subject: Change docs with method for uploading questions --- .../moderator_docs/creating_question.rst | 31 ++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'yaksh') diff --git a/yaksh/documentation/moderator_docs/creating_question.rst b/yaksh/documentation/moderator_docs/creating_question.rst index f99bf7f..94bb95c 100644 --- a/yaksh/documentation/moderator_docs/creating_question.rst +++ b/yaksh/documentation/moderator_docs/creating_question.rst @@ -264,6 +264,37 @@ Features in Question Click on the browse button. This will open up a window. Select the zip file of questions and click Ok and then click on Upload file button, questions will be uploaded and displayed on the Questions page. + Zip file should contain **questions_dump.json** from which questions will be loaded. + Zip file can contain files related to questions. + Sample entry in **questions_dump.json** is as shown below. :: + [{ + "snippet": "", + "testcase": [ + { + "test_case_args": "", + "test_case_type": "standardtestcase", + "weight": 1.0, + "test_case": "Test Case here" + }, + ], + "points": 2.0, + "description": "Question Description here", + "language": "python", + "active": true, + "type": "code", + "files": [[demo1.txt, false], [demo2.zip, true]], + "summary": "Question Summary here" + }] + + .. Note:: 1. In **files** entry in json, the list contains two items which + are filename (demo1.txt) and extract status (false) i.e file needs to extracted or not. + + 2. If there are no files then **files** entry can be empty + i.e it should be "files": []. + + 3. From sample, zip file should contain demo1.txt and demo2.zip since it is + required for question. + * **Test Questions** Select questions from the list of question displayed on the Questions page. Click on Test selected button. This will take you to a quiz with the selected questions. -- cgit From 69ab40cc3d4d769d0d3f1c783f950cac52f7935e Mon Sep 17 00:00:00 2001 From: adityacp Date: Thu, 16 Mar 2017 17:15:38 +0530 Subject: Fix test cases for loading questions --- yaksh/models.py | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'yaksh') diff --git a/yaksh/models.py b/yaksh/models.py index dc015d5..c10f953 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -318,18 +318,17 @@ class Question(models.Model): file_names = question.pop('files') test_cases = question.pop('testcase') que, result = Question.objects.get_or_create(**question) - if not result: - if file_names: - que._add_files_to_db(file_names, file_path) - for test_case in test_cases: - test_case_type = test_case.pop('test_case_type') - model_class = get_model_class(test_case_type) - new_test_case, obj_create_status = \ - model_class.objects.get_or_create( - question=que, **test_case - ) - new_test_case.type = test_case_type - new_test_case.save() + if file_names: + que._add_files_to_db(file_names, file_path) + for test_case in test_cases: + test_case_type = test_case.pop('test_case_type') + model_class = get_model_class(test_case_type) + new_test_case, obj_create_status = \ + model_class.objects.get_or_create( + question=que, **test_case + ) + new_test_case.type = test_case_type + new_test_case.save() if files_list: delete_files(files_list, file_path) -- cgit From 8547c5bfe7be64256b412f484ab6a9f60628ef06 Mon Sep 17 00:00:00 2001 From: adityacp Date: Thu, 16 Mar 2017 19:00:48 +0530 Subject: Handle json file syntax errors in uploading question --- yaksh/models.py | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) (limited to 'yaksh') diff --git a/yaksh/models.py b/yaksh/models.py index c10f953..80e215e 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -15,6 +15,8 @@ except ImportError: from io import BytesIO as string_io import pytz import os +import sys +import traceback import stat from os.path import join, exists import shutil @@ -312,7 +314,13 @@ class Question(models.Model): def load_questions(self, questions_list, user, file_path=None, files_list=None): - questions = json.loads(questions_list) + try: + questions = json.loads(questions_list) + except json.decoder.JSONDecodeError: + exc_type, exc_value, exc_tb = sys.exc_info() + tb_list = traceback.format_exception(exc_type, exc_value, exc_tb) + msg = "Error Parsing Json: {0}".format(tb_list[-1]) + return msg for question in questions: question['user'] = user file_names = question.pop('files') @@ -329,9 +337,7 @@ class Question(models.Model): ) new_test_case.type = test_case_type new_test_case.save() - - if files_list: - delete_files(files_list, file_path) + return "Questions Uploaded Successfully" def get_test_cases(self, **kwargs): tc_list = [] @@ -399,17 +405,17 @@ class Question(models.Model): def read_json(self, file_path, user, files=None): json_file = os.path.join(file_path, "questions_dump.json") + msg = "" if os.path.exists(json_file): with open(json_file, 'r') as q_file: questions_list = q_file.read() - try: - self.load_questions(questions_list, user, file_path, files) - except ValueError: - return "Syntax Error in Json. Please check your json file." - - return "Questions Uploaded Successfully" + msg = self.load_questions(questions_list, user, file_path, files) else: - return "Please upload zip file with questions_dump.json in it." + msg = "Please upload zip file with questions_dump.json in it." + + if files: + delete_files(files, file_path) + return msg def create_demo_questions(self, user): zip_file_path = os.path.join( -- cgit From 6c53c90ee5dd7184889fd3f99130b194e75fef4c Mon Sep 17 00:00:00 2001 From: adityacp Date: Fri, 17 Mar 2017 13:57:21 +0530 Subject: Change Exception message for load questions --- yaksh/models.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'yaksh') diff --git a/yaksh/models.py b/yaksh/models.py index 80e215e..970f136 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -316,10 +316,8 @@ class Question(models.Model): files_list=None): try: questions = json.loads(questions_list) - except json.decoder.JSONDecodeError: - exc_type, exc_value, exc_tb = sys.exc_info() - tb_list = traceback.format_exception(exc_type, exc_value, exc_tb) - msg = "Error Parsing Json: {0}".format(tb_list[-1]) + except ValueError as exc_msg: + msg = "Error Parsing Json: {0}".format(exc_msg) return msg for question in questions: question['user'] = user -- cgit