From f1eb06d3740eb21558576e5f5489972e45cab038 Mon Sep 17 00:00:00 2001 From: adityacp Date: Wed, 15 Mar 2017 15:38:01 +0530 Subject: Changes in Views and Models - Add new boolean field in Question model whether to check assignment upload or not - In views before uploading a assignment file, check if it already exists and delete previous file - Grade assignment file with hook code --- yaksh/models.py | 11 +++++++++-- yaksh/views.py | 32 ++++++++++++++++++++++---------- 2 files changed, 31 insertions(+), 12 deletions(-) (limited to 'yaksh') diff --git a/yaksh/models.py b/yaksh/models.py index 398f508..9134663 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -66,7 +66,7 @@ test_status = ( def get_assignment_dir(instance, filename): return os.sep.join(( - instance.user.user, instance.assignmentQuestion.id, filename + str(instance.user.user), str(instance.assignmentQuestion.id), filename )) @@ -264,6 +264,9 @@ class Question(models.Model): # Does this question allow partial grading partial_grading = models.BooleanField(default=False) + # Check assignment upload based question + grade_assignment_upload = models.BooleanField(default=False) + def consolidate_answer_data(self, user_answer): question_data = {} metadata = {} @@ -280,9 +283,13 @@ class Question(models.Model): metadata['language'] = self.language metadata['partial_grading'] = self.partial_grading files = FileUpload.objects.filter(question=self) + assignment_files = AssignmentUpload.objects.filter() if files: metadata['file_paths'] = [(file.file.path, file.extract) for file in files] + if assignment_files: + metadata['assign_files'] = [(file.assignmentFile.path, False) + for file in assignment_files] question_data['metadata'] = metadata return json.dumps(question_data) @@ -1201,7 +1208,7 @@ class AnswerPaper(models.Model): ############################################################################### class AssignmentUpload(models.Model): - user = models.ForeignKey(Profile) + user = models.ForeignKey(User) assignmentQuestion = models.ForeignKey(Question) assignmentFile = models.FileField(upload_to=get_assignment_dir) diff --git a/yaksh/views.py b/yaksh/views.py index 63653e6..4cdba5c 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -467,17 +467,24 @@ def check(request, q_id, attempt_num=None, questionpaper_id=None): elif current_question.type == 'mcc': user_answer = request.POST.getlist('answer') elif current_question.type == 'upload': - assign = AssignmentUpload() - assign.user = user.profile - assign.assignmentQuestion = current_question # if time-up at upload question then the form is submitted without # validation if 'assignment' in request.FILES: - assign.assignmentFile = request.FILES['assignment'] - assign.save() + assignment_filename = request.FILES.getlist('assignment') + for fname in assignment_filename: + if AssignmentUpload.objects.filter( + assignmentFile__icontains=fname, user=user).exists(): + assign_file = AssignmentUpload.objects.get( + assignmentFile__icontains=fname, user=user) + os.remove(assign_file.assignmentFile.path) + assign_file.delete() + AssignmentUpload.objects.create(user=user, + assignmentQuestion=current_question, assignmentFile=fname + ) user_answer = 'ASSIGNMENT UPLOADED' - next_q = paper.add_completed_question(current_question.id) - return show_question(request, next_q, paper) + if not current_question.grade_assignment_upload: + next_q = paper.add_completed_question(current_question.id) + return show_question(request, next_q, paper) else: user_code = request.POST.get('answer') user_answer = snippet_code + "\n" + user_code if snippet_code else user_code @@ -497,7 +504,9 @@ def check(request, q_id, attempt_num=None, questionpaper_id=None): if result.get('success'): new_answer.marks = (current_question.points * result['weight'] / current_question.get_maximum_test_case_weight()) \ - if current_question.partial_grading and current_question.type == 'code' else current_question.points + if current_question.partial_grading and \ + current_question.type == 'code' or current_question.type == 'upload' \ + else current_question.points new_answer.correct = result.get('success') error_message = None new_answer.error = json.dumps(result.get('error')) @@ -505,11 +514,14 @@ def check(request, q_id, attempt_num=None, questionpaper_id=None): else: new_answer.marks = (current_question.points * result['weight'] / current_question.get_maximum_test_case_weight()) \ - if current_question.partial_grading and current_question.type == 'code' else 0 + if current_question.partial_grading and \ + current_question.type == 'code' or current_question.type == 'upload' \ + else 0 error_message = result.get('error') if current_question.type == 'code' \ - else None + or current_question.type == 'upload' else None new_answer.error = json.dumps(result.get('error')) next_question = current_question if current_question.type == 'code' \ + or current_question.type == 'upload' \ else paper.add_completed_question(current_question.id) new_answer.save() paper.update_marks('inprogress') -- cgit From 5e500f3344a13d375d018312936280d88d47c93c Mon Sep 17 00:00:00 2001 From: adityacp Date: Wed, 15 Mar 2017 17:55:34 +0530 Subject: Change templates and js - Support multiple files uploading in assignment - Create new check field to grade assignement based question - Add js changes --- yaksh/hook_evaluator.py | 7 +++++++ yaksh/static/yaksh/js/add_question.js | 36 ++++++++++++++++++++++++--------- yaksh/templates/exam.html | 2 +- yaksh/templates/yaksh/add_question.html | 1 + yaksh/templates/yaksh/question.html | 2 +- 5 files changed, 37 insertions(+), 11 deletions(-) (limited to 'yaksh') diff --git a/yaksh/hook_evaluator.py b/yaksh/hook_evaluator.py index 2cc4578..052d220 100644 --- a/yaksh/hook_evaluator.py +++ b/yaksh/hook_evaluator.py @@ -17,6 +17,7 @@ class HookEvaluator(BaseEvaluator): self.user_answer = metadata.get('user_answer') self.file_paths = metadata.get('file_paths') self.partial_grading = metadata.get('partial_grading') + self.assignment_files = metadata.get('assign_files') # Set test case data values self.hook_code = test_case_data.get('hook_code') @@ -26,6 +27,8 @@ class HookEvaluator(BaseEvaluator): # Delete the created file. if self.files: delete_files(self.files) + if self.assign_files: + delete_files(self.assign_files) def check_code(self): """ Function evaluates user answer by running a python based hook code @@ -47,6 +50,10 @@ class HookEvaluator(BaseEvaluator): Returns (False, error_msg, 0.0): If mandatory arguments are not files or if the required permissions are not given to the file(s). """ + if self.file_paths: + self.files = copy_files(self.file_paths) + if self.assignment_files: + self.assign_files = copy_files(self.assignment_files) success = False mark_fraction = 0.0 try: diff --git a/yaksh/static/yaksh/js/add_question.js b/yaksh/static/yaksh/js/add_question.js index 8ca22eb..05752b4 100644 --- a/yaksh/static/yaksh/js/add_question.js +++ b/yaksh/static/yaksh/js/add_question.js @@ -111,16 +111,34 @@ function textareaformat() }); - $('#id_type').bind('focus', function(event){ - var type = document.getElementById('id_type'); - type.style.border = '1px solid #ccc'; - }); + $('#id_type').bind('focus', function(event){ + var type = document.getElementById('id_type'); + type.style.border = '1px solid #ccc'; + }); + + $('#id_language').bind('focus', function(event){ + var language = document.getElementById('id_language'); + language.style.border = '1px solid #ccc'; + }); + document.getElementById('my').innerHTML = document.getElementById('id_description').value ; - $('#id_language').bind('focus', function(event){ - var language = document.getElementById('id_language'); - language.style.border = '1px solid #ccc'; - }); - document.getElementById('my').innerHTML = document.getElementById('id_description').value ; + + if (document.getElementById('id_grade_assignment_upload').checked || + document.getElementById('id_type').val() == 'upload'){ + $("#id_grade_assignment_upload").prop("disabled", false); + } + else{ + $("#id_grade_assignment_upload").prop("disabled", true); + } + + $('#id_type').change(function() { + if ($(this).val() == "upload"){ + $("#id_grade_assignment_upload").prop("disabled", false); + } + else{ + $("#id_grade_assignment_upload").prop("disabled", true); + } + }); } function autosubmit() diff --git a/yaksh/templates/exam.html b/yaksh/templates/exam.html index 02ff70a..a18a962 100644 --- a/yaksh/templates/exam.html +++ b/yaksh/templates/exam.html @@ -73,7 +73,7 @@ {% block main %} {% endblock %} - {% if question.type == 'code' %} + {% if question.type == 'code' or question.type == 'upload' %} {% if error_message %}
{% for error in error_message %} diff --git a/yaksh/templates/yaksh/add_question.html b/yaksh/templates/yaksh/add_question.html index 75802b4..ae70774 100644 --- a/yaksh/templates/yaksh/add_question.html +++ b/yaksh/templates/yaksh/add_question.html @@ -25,6 +25,7 @@ Tags: {{ qform.tags }} Snippet: {{ qform.snippet }} Partial Grading: {{ qform.partial_grading }} + Grade Assignment Upload: {{ qform.grade_assignment_upload }} File: {{ fileform.file_field }}{{ fileform.file_field.errors }} {% if uploaded_files %}
Uploaded files:
Check on delete to delete files, extract to extract files and hide to hide files from student(if required)
diff --git a/yaksh/templates/yaksh/question.html b/yaksh/templates/yaksh/question.html index 9dd0de5..2a93cfb 100644 --- a/yaksh/templates/yaksh/question.html +++ b/yaksh/templates/yaksh/question.html @@ -188,7 +188,7 @@ function call_skip(url) {% endif %} {% if question.type == "upload" %}

Upload assignment file for the said question

- +


{% endif %} {% if question.type == "code" %} -- cgit From e937c2a3a17bfc127af89a86e213e434350cd360 Mon Sep 17 00:00:00 2001 From: adityacp Date: Wed, 15 Mar 2017 18:12:31 +0530 Subject: Change assignment dir path and add condition for json data --- yaksh/models.py | 4 ++-- yaksh/views.py | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'yaksh') diff --git a/yaksh/models.py b/yaksh/models.py index 9134663..4dcd2ec 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -66,7 +66,7 @@ test_status = ( def get_assignment_dir(instance, filename): return os.sep.join(( - str(instance.user.user), str(instance.assignmentQuestion.id), filename + instance.user.username, str(instance.assignmentQuestion.id), filename )) @@ -1145,7 +1145,7 @@ class AnswerPaper(models.Model): if set(user_answer) == set(expected_answers): result['success'] = True result['error'] = ['Correct answer'] - elif question.type == 'code': + elif question.type == 'code' or question.type == "upload": user_dir = self.user.profile.get_user_dir() json_result = code_server.run_code( question.language, json_data, user_dir diff --git a/yaksh/views.py b/yaksh/views.py index 4cdba5c..d4d11f5 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -473,8 +473,10 @@ def check(request, q_id, attempt_num=None, questionpaper_id=None): assignment_filename = request.FILES.getlist('assignment') for fname in assignment_filename: if AssignmentUpload.objects.filter( + assignmentQuestion=current_question, assignmentFile__icontains=fname, user=user).exists(): assign_file = AssignmentUpload.objects.get( + assignmentQuestion=current_question, assignmentFile__icontains=fname, user=user) os.remove(assign_file.assignmentFile.path) assign_file.delete() @@ -499,7 +501,8 @@ def check(request, q_id, attempt_num=None, questionpaper_id=None): # questions, we obtain the results via XML-RPC with the code executed # safely in a separate process (the code_server.py) running as nobody. json_data = current_question.consolidate_answer_data(user_answer) \ - if current_question.type == 'code' else None + if current_question.type == 'code' or \ + current_question.type == 'upload' else None result = paper.validate_answer(user_answer, current_question, json_data) if result.get('success'): new_answer.marks = (current_question.points * result['weight'] / -- cgit From c6b9b51a5c4b1c676c9784432435ccffb15335b6 Mon Sep 17 00:00:00 2001 From: adityacp Date: Thu, 16 Mar 2017 10:47:21 +0530 Subject: Add test for assignment evaluation and Change test_models --- yaksh/evaluator_tests/test_python_evaluation.py | 56 +++++++++++++++++++++---- yaksh/test_models.py | 34 +++++++++------ 2 files changed, 70 insertions(+), 20 deletions(-) (limited to 'yaksh') diff --git a/yaksh/evaluator_tests/test_python_evaluation.py b/yaksh/evaluator_tests/test_python_evaluation.py index 51f9bea..a751c40 100644 --- a/yaksh/evaluator_tests/test_python_evaluation.py +++ b/yaksh/evaluator_tests/test_python_evaluation.py @@ -19,7 +19,8 @@ class EvaluatorBaseTest(unittest.TestCase): class PythonAssertionEvaluationTestCases(EvaluatorBaseTest): def setUp(self): - with open('/tmp/test.txt', 'wb') as f: + self.tmp_file = os.path.join(tempfile.gettempdir(), "test.txt") + with open(self.tmp_file, 'wb') as f: f.write('2'.encode('ascii')) tmp_in_dir_path = tempfile.mkdtemp() self.in_dir = tmp_in_dir_path @@ -33,7 +34,7 @@ class PythonAssertionEvaluationTestCases(EvaluatorBaseTest): self.file_paths = None def tearDown(self): - os.remove('/tmp/test.txt') + os.remove(self.tmp_file) shutil.rmtree(self.in_dir) def test_correct_answer(self): @@ -343,7 +344,7 @@ class PythonAssertionEvaluationTestCases(EvaluatorBaseTest): def test_file_based_assert(self): # Given self.test_case_data = [{"test_case_type": "standardtestcase", "test_case": "assert(ans()=='2')", "weight": 0.0}] - self.file_paths = [('/tmp/test.txt', False)] + self.file_paths = [(self.tmp_file, False)] user_answer = dedent(""" def ans(): with open("test.txt") as f: @@ -479,12 +480,17 @@ class PythonAssertionEvaluationTestCases(EvaluatorBaseTest): class PythonStdIOEvaluationTestCases(EvaluatorBaseTest): def setUp(self): - with open('/tmp/test.txt', 'wb') as f: + self.tmp_file = os.path.join(tempfile.gettempdir(), "test.txt") + with open(self.tmp_file, 'wb') as f: f.write('2'.encode('ascii')) self.file_paths = None tmp_in_dir_path = tempfile.mkdtemp() self.in_dir = tmp_in_dir_path + def teardown(self): + os.remove(self.tmp_file) + shutil.rmtree(self.in_dir) + def test_correct_answer_integer(self): # Given self.test_case_data = [{"test_case_type": "stdiobasedtestcase", @@ -618,7 +624,7 @@ class PythonStdIOEvaluationTestCases(EvaluatorBaseTest): "expected_output": "2", "weight": 0.0 }] - self.file_paths = [('/tmp/test.txt', False)] + self.file_paths = [(self.tmp_file, False)] user_answer = dedent(""" with open("test.txt") as f: @@ -702,7 +708,8 @@ class PythonStdIOEvaluationTestCases(EvaluatorBaseTest): class PythonHookEvaluationTestCases(EvaluatorBaseTest): def setUp(self): - with open('/tmp/test.txt', 'wb') as f: + self.tmp_file = os.path.join(tempfile.gettempdir(), "test.txt") + with open(self.tmp_file, 'wb') as f: f.write('2'.encode('ascii')) tmp_in_dir_path = tempfile.mkdtemp() self.in_dir = tmp_in_dir_path @@ -712,7 +719,7 @@ class PythonHookEvaluationTestCases(EvaluatorBaseTest): self.file_paths = None def tearDown(self): - os.remove('/tmp/test.txt') + os.remove(self.tmp_file) shutil.rmtree(self.in_dir) def test_correct_answer(self): @@ -910,6 +917,41 @@ class PythonHookEvaluationTestCases(EvaluatorBaseTest): self.assertFalse(result.get('success')) self.assert_correct_output(self.timeout_msg, result.get('error')) + def test_assignment_upload(self): + # Given + user_answer = "Assignment Upload" + hook_code = dedent("""\ + def check_answer(user_answer): + success = False + err = "Incorrect Answer" + mark_fraction = 0.0 + with open("test.txt") as f: + data = f.read() + if data == '2': + success, err, mark_fraction = True, "", 1.0 + return success, err, mark_fraction + """ + ) + test_case_data = [{"test_case_type": "hooktestcase", + "hook_code": hook_code,"weight": 1.0 + }] + kwargs = { + 'metadata': { + 'user_answer': user_answer, + 'file_paths': self.file_paths, + 'assign_files': [(self.tmp_file, False)], + 'partial_grading': False, + 'language': 'python' + }, + 'test_case_data': test_case_data, + } + + # When + grader = Grader(self.in_dir) + result = grader.evaluate(kwargs) + + # Then + self.assertTrue(result.get('success')) if __name__ == '__main__': unittest.main() diff --git a/yaksh/test_models.py b/yaksh/test_models.py index cd66aed..56097a7 100644 --- a/yaksh/test_models.py +++ b/yaksh/test_models.py @@ -57,20 +57,15 @@ def setUpModule(): description='demo quiz', pass_criteria=40, language='Python', prerequisite=quiz, course=course, instructions="Demo Instructions") - - with open('/tmp/test.txt', 'wb') as f: + tmp_file1 = os.path.join(tempfile.gettempdir(), "test.txt") + with open(tmp_file1, 'wb') as f: f.write('2'.encode('ascii')) + def tearDownModule(): User.objects.all().delete() Question.objects.all().delete() Quiz.objects.all().delete() - - que_id_list = ["25", "22", "24", "27"] - for que_id in que_id_list: - dir_path = os.path.join(os.getcwd(), "yaksh", "data","question_{0}".format(que_id)) - if os.path.exists(dir_path): - shutil.rmtree(dir_path) ############################################################################### class ProfileTestCases(unittest.TestCase): @@ -117,7 +112,7 @@ class QuestionTestCases(unittest.TestCase): self.question2.save() # create a temp directory and add files for loading questions test - file_path = "/tmp/test.txt" + file_path = os.path.join(tempfile.gettempdir(), "test.txt") self.load_tmp_path = tempfile.mkdtemp() shutil.copy(file_path, self.load_tmp_path) file1 = os.path.join(self.load_tmp_path, "test.txt") @@ -126,9 +121,11 @@ class QuestionTestCases(unittest.TestCase): self.dump_tmp_path = tempfile.mkdtemp() shutil.copy(file_path, self.dump_tmp_path) file2 = os.path.join(self.dump_tmp_path, "test.txt") - file = open(file2, "r") - django_file = File(file) - file = FileUpload.objects.create(file=django_file, question=self.question2) + upload_file = open(file2, "r") + django_file = File(upload_file) + file = FileUpload.objects.create(file=django_file, + question=self.question2 + ) self.question1.tags.add('python', 'function') self.assertion_testcase = StandardTestCase(question=self.question1, @@ -158,6 +155,15 @@ class QuestionTestCases(unittest.TestCase): def tearDown(self): shutil.rmtree(self.load_tmp_path) shutil.rmtree(self.dump_tmp_path) + uploaded_files = FileUpload.objects.all() + que_id_list = [file.question.id for file in uploaded_files] + for que_id in que_id_list: + dir_path = os.path.join(os.getcwd(), "yaksh", "data", + "question_{0}".format(que_id) + ) + if os.path.exists(dir_path): + shutil.rmtree(dir_path) + uploaded_files.delete() def test_question(self): """ Test question """ @@ -214,7 +220,9 @@ class QuestionTestCases(unittest.TestCase): self.assertTrue(question_data.active) self.assertEqual(question_data.snippet, 'def fact()') self.assertEqual(os.path.basename(file.file.path), "test.txt") - self.assertEqual([case.get_field_value() for case in test_case], self.test_case_upload_data) + self.assertEqual([case.get_field_value() for case in test_case], + self.test_case_upload_data + ) ############################################################################### -- cgit From 5ae3841e4c432d5c0ee378ac9a4142f205b1dbb6 Mon Sep 17 00:00:00 2001 From: adityacp Date: Fri, 17 Mar 2017 20:47:55 +0530 Subject: Change consolidate_answer_data to get assignment uploads --- yaksh/models.py | 16 ++++++++++------ yaksh/views.py | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) (limited to 'yaksh') diff --git a/yaksh/models.py b/yaksh/models.py index 4dcd2ec..f6efeba 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -267,7 +267,7 @@ class Question(models.Model): # Check assignment upload based question grade_assignment_upload = models.BooleanField(default=False) - def consolidate_answer_data(self, user_answer): + def consolidate_answer_data(self, user_answer, user=None): question_data = {} metadata = {} test_case_data = [] @@ -283,13 +283,16 @@ class Question(models.Model): metadata['language'] = self.language metadata['partial_grading'] = self.partial_grading files = FileUpload.objects.filter(question=self) - assignment_files = AssignmentUpload.objects.filter() if files: metadata['file_paths'] = [(file.file.path, file.extract) for file in files] - if assignment_files: - metadata['assign_files'] = [(file.assignmentFile.path, False) - for file in assignment_files] + if self.type == "upload": + assignment_files = AssignmentUpload.objects.filter( + assignmentQuestion=self, user=user + ) + if assignment_files: + metadata['assign_files'] = [(file.assignmentFile.path, False) + for file in assignment_files] question_data['metadata'] = metadata return json.dumps(question_data) @@ -1272,7 +1275,8 @@ class HookTestCase(TestCase): success - Boolean, indicating if code was executed correctly mark_fraction - Float, indicating fraction of the weight to a test case - error - String, error message if success is false''' + error - String, error message if success is false + In case of assignment upload there will be no user answer ''' success = False err = "Incorrect Answer" # Please make this more specific mark_fraction = 0.0 diff --git a/yaksh/views.py b/yaksh/views.py index d4d11f5..bd3540d 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -500,7 +500,7 @@ def check(request, q_id, attempt_num=None, questionpaper_id=None): # If we were not skipped, we were asked to check. For any non-mcq # questions, we obtain the results via XML-RPC with the code executed # safely in a separate process (the code_server.py) running as nobody. - json_data = current_question.consolidate_answer_data(user_answer) \ + json_data = current_question.consolidate_answer_data(user_answer, user) \ if current_question.type == 'code' or \ current_question.type == 'upload' else None result = paper.validate_answer(user_answer, current_question, json_data) -- cgit From b4b33cc37244ed59765c705c6d882c00ddc88c62 Mon Sep 17 00:00:00 2001 From: adityacp Date: Fri, 17 Mar 2017 20:49:13 +0530 Subject: Intialize empty list for assignment files in hook --- yaksh/hook_evaluator.py | 1 + 1 file changed, 1 insertion(+) (limited to 'yaksh') diff --git a/yaksh/hook_evaluator.py b/yaksh/hook_evaluator.py index 052d220..0819ec9 100644 --- a/yaksh/hook_evaluator.py +++ b/yaksh/hook_evaluator.py @@ -12,6 +12,7 @@ from .grader import TimeoutException class HookEvaluator(BaseEvaluator): def __init__(self, metadata, test_case_data): self.files = [] + self.assign_files = [] # Set metadata values self.user_answer = metadata.get('user_answer') -- cgit From e0beba1dacb0d5de5ca8b59298345eb9d841d879 Mon Sep 17 00:00:00 2001 From: adityacp Date: Fri, 17 Mar 2017 22:17:31 +0530 Subject: Add grade_assignment_upload field to inital migrations --- yaksh/migrations/0001_initial.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'yaksh') diff --git a/yaksh/migrations/0001_initial.py b/yaksh/migrations/0001_initial.py index 8ee8c6a..8770a72 100644 --- a/yaksh/migrations/0001_initial.py +++ b/yaksh/migrations/0001_initial.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Generated by Django 1.9.5 on 2017-03-14 08:33 +# Generated by Django 1.9.5 on 2017-03-17 16:42 from __future__ import unicode_literals import datetime @@ -114,6 +114,7 @@ class Migration(migrations.Migration): ('active', models.BooleanField(default=True)), ('snippet', models.CharField(blank=True, max_length=256)), ('partial_grading', models.BooleanField(default=False)), + ('grade_assignment_upload', models.BooleanField(default=False)), ('tags', taggit.managers.TaggableManager(blank=True, help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags')), ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='user', to=settings.AUTH_USER_MODEL)), ], @@ -171,7 +172,7 @@ class Migration(migrations.Migration): name='HookTestCase', fields=[ ('testcase_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='yaksh.TestCase')), - ('hook_code', models.TextField(default='def check_answer(user_answer):\n \'\'\' Evaluates user answer to return -\n success - Boolean, indicating if code was executed correctly\n mark_fraction - Float, indicating fraction of the\n weight to a test case\n error - String, error message if success is false\'\'\'\n success = False\n err = "Incorrect Answer" # Please make this more specific\n mark_fraction = 0.0\n\n # write your code here\n\n return success, err, mark_fraction\n\n')), + ('hook_code', models.TextField(default='def check_answer(user_answer):\n \'\'\' Evaluates user answer to return -\n success - Boolean, indicating if code was executed correctly\n mark_fraction - Float, indicating fraction of the\n weight to a test case\n error - String, error message if success is false\n In case of assignment upload there will be no user answer \'\'\'\n success = False\n err = "Incorrect Answer" # Please make this more specific\n mark_fraction = 0.0\n\n # write your code here\n\n return success, err, mark_fraction\n\n')), ('weight', models.FloatField(default=1.0)), ], bases=('yaksh.testcase',), @@ -233,7 +234,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='assignmentupload', name='user', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='yaksh.Profile'), + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), ), migrations.AddField( model_name='answerpaper', -- cgit