diff options
-rw-r--r-- | yaksh/models.py | 81 | ||||
-rw-r--r-- | yaksh/templates/yaksh/question.html | 9 | ||||
-rw-r--r-- | yaksh/templates/yaksh/upload_file.html | 32 | ||||
-rw-r--r-- | yaksh/urls.py | 4 | ||||
-rw-r--r-- | yaksh/views.py | 75 |
5 files changed, 198 insertions, 3 deletions
diff --git a/yaksh/models.py b/yaksh/models.py index e2b9952..e9b2c1b 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -26,6 +26,8 @@ import tempfile from textwrap import dedent from ast import literal_eval import pandas as pd +import qrcode +import hashlib # Django Imports from django.db import models @@ -2923,7 +2925,7 @@ class TOCManager(models.Manager): topic = Topic.objects.create(**content) toc.append(TableOfContents( course_id=course_id, lesson_id=lesson_id, time=time, - content_object=topic, content=content_type + content_object=topic, content=content_type )) messages.append((True, f"{topic.name} added successfully")) else: @@ -3175,3 +3177,80 @@ class MicroManager(models.Model): def __str__(self): return 'MicroManager for {0} - {1}'.format(self.student.username, self.course.name) + + +class QRcode(models.Model): + random_key = models.CharField(max_length=128, blank=True) + short_key = models.CharField(max_length=128, null=True, unique=True) + image = models.ImageField(upload_to='qrcode', blank=True) + used = models.BooleanField(default=False) + active = models.BooleanField(default=False) + handler = models.ForeignKey('QRcodeHandler', on_delete=models.CASCADE) + + def __str__(self): + return 'QRcode {0}'.format(self.short_key) + + def is_active(self): + return self.active + + def is_used(self): + return self.used + + def deactivate(self): + self.active = False + + def activate(self): + self.active = True + + def set_used(self): + self.used = True + + def set_random_key(self): + key = hashlib.sha1('{0}'.format(self.id).encode()).hexdigest() + self.random_key = key + + def set_short_key(self): + key = self.random_key + if key: + num = 5 + for i in range(40): + try: + self.short_key = key[0 : num] + break + except django.db.IntegrityError: + num = num + 1 + + def generate_image(self, content): + img = qrcode.make(content) + path = os.path.join(settings.MEDIA_ROOT, 'qrcode', + '{0}.png'.format(self.short_key)) + img.save(path) + self.image = os.path.join('qrcode', '{0}.png'.format(self.short_key)) + self.activate() + + +class QRcodeHandler(models.Model): + user = models.ForeignKey(User, on_delete=models.CASCADE) + answerpaper = models.ForeignKey(AnswerPaper, on_delete=models.CASCADE) + question = models.ForeignKey(Question, on_delete=models.CASCADE) + + + def __str__(self): + return 'QRcode Handler for {0}'.format(self.user.username) + + def get_qrcode(self): + qrcodes = self.qrcode_set.filter(active=True, used=False) + if qrcodes.exists(): + return qrcodes.last() + else: + return self._create_qrcode() + + def _create_qrcode(self): + qrcode = QRcode.objects.create(handler=self) + qrcode.set_random_key() + qrcode.set_short_key() + return qrcode + + def can_use(self): + return self.answerpaper.is_attempt_inprogress() + diff --git a/yaksh/templates/yaksh/question.html b/yaksh/templates/yaksh/question.html index 2dbfeed..9189324 100644 --- a/yaksh/templates/yaksh/question.html +++ b/yaksh/templates/yaksh/question.html @@ -285,6 +285,14 @@ question_type = "{{ question.type }}"; {% endfor %} </ul> {% endif %} + {% if qrcode %} + <img src="{{ qrcode.image.url }}"> + {% else %} + <a class="active btn btn-outline-primary " href="#"data-toggle="tooltip" + title="Upload from any device using the QR Code" + onclick="call_skip('{% url 'yaksh:generate_qrcode' paper.id question.id module.id %}')">Generate QR Code</a> + {% endif %} + <p></p> {% endif %} <!-- Arrange type question --> @@ -365,7 +373,6 @@ question_type = "{{ question.type }}"; {% if question.type == 'code' or question.type == 'upload' %} <div id="error_panel"></div> {% endif %} - <!-- Modal --> <div class="modal" id="upload_alert" > <div class="modal-dialog"> diff --git a/yaksh/templates/yaksh/upload_file.html b/yaksh/templates/yaksh/upload_file.html new file mode 100644 index 0000000..04d8b09 --- /dev/null +++ b/yaksh/templates/yaksh/upload_file.html @@ -0,0 +1,32 @@ +<html> +<title> Upload File </title> + +<script> +function validate(){ + uploaded_file = document.getElementById("assignment").value; + if(uploaded_file == ""){ + $("#upload_alert").modal("show"); + return false; + } + return true; +} +</script> +<style> +div, input, button { + font-size: x-large; + text-align: center; +} +</style> +<div> +{% if success %} + <p> {{ msg }}</p> +{% else %} + <form id="code" action="{% url 'yaksh:upload_file' key %}" method="post" enctype="multipart/form-data"> + {% csrf_token %} + <h3>Upload assignment file for {{ question.summary }}</h3> + <input type=file id="assignment" name="assignment" multiple=""> + <button class="btn btn-success" type="submit" name="check" id="check" onClick="return validate();">Upload</button> + </form> +{% endif %} +</div> +</html> diff --git a/yaksh/urls.py b/yaksh/urls.py index e93d80a..f75df3d 100644 --- a/yaksh/urls.py +++ b/yaksh/urls.py @@ -156,6 +156,10 @@ urlpatterns = [ name="questions_filter"), url(r'^editprofile/$', views.edit_profile, name='edit_profile'), url(r'^viewprofile/$', views.view_profile, name='view_profile'), + url(r'^generate_qrcode/(?P<answerpaper_id>\d+)/(?P<question_id>\d+)/(?P<module_id>\d+)/$', + views.generate_qrcode, name='generate_qrcode'), + url(r'^upload_file/(?P<key>.+)/$', + views.upload_file, name='upload_file'), url(r'^manage/searchteacher/(?P<course_id>\d+)/$', views.search_teacher, name="search_teacher"), diff --git a/yaksh/views.py b/yaksh/views.py index b3b1e02..63a41af 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -40,7 +40,8 @@ from yaksh.models import ( StdIOBasedTestCase, StringTestCase, TestCase, User, get_model_class, FIXTURES_DIR_PATH, MOD_GROUP_NAME, Lesson, LessonFile, LearningUnit, LearningModule, CourseStatus, question_types, Post, Comment, - Topic, TableOfContents, LessonQuizAnswer, MicroManager + Topic, TableOfContents, LessonQuizAnswer, MicroManager, QRcode, + QRcodeHandler ) from yaksh.forms import ( UserRegisterForm, UserLoginForm, QuizForm, QuestionForm, @@ -57,6 +58,7 @@ from .send_emails import (send_user_mail, from .decorators import email_verified, has_profile from .tasks import regrade_papers from notifications_plugin.models import Notification +import hashlib def my_redirect(url): @@ -671,6 +673,7 @@ def show_question(request, question, paper, error_message=None, quiz_type = 'Exam' can_skip = False assignment_files = [] + qrcode = [] if previous_question: delay_time = paper.time_left_on_question(previous_question) else: @@ -719,6 +722,13 @@ def show_question(request, question, paper, error_message=None, user=request.user, question_paper_id=paper.question_paper_id ) + handlers = QRcodeHandler.objects.filter(user=request.user, + question=question, + answerpaper=paper) + qrcode = None + if handlers.exists(): + handler = handlers.last() + qrcode = handler.qrcode_set.filter(active=True, used=False).last() files = FileUpload.objects.filter(question_id=question.id, hide=False) course = Course.objects.get(id=course_id) module = course.learning_module.get(id=module_id) @@ -739,6 +749,7 @@ def show_question(request, question, paper, error_message=None, 'quiz_type': quiz_type, 'all_modules': all_modules, 'assignment_files': assignment_files, + 'qrcode': qrcode, } answers = paper.get_previous_answers(question) if answers: @@ -4136,3 +4147,65 @@ def _read_marks_csv(request, reader, course, question_paper, question_ids): messages.info(request, 'Updated successfully for user: {0}, question: {1}'.format( username, question.summary)) + + +@login_required +@email_verified +def generate_qrcode(request, answerpaper_id, question_id, module_id): + user = request.user + answerpaper = get_object_or_404(AnswerPaper, pk=answerpaper_id) + question = get_object_or_404(Question, pk=question_id) + + if not answerpaper.is_attempt_inprogress(): + pass + handler = QRcodeHandler.objects.get_or_create(user=user, question=question, + answerpaper=answerpaper)[0] + qrcode = handler.get_qrcode() + content = '{0}/exam/upload_file/{1}'.format(URL_ROOT, qrcode.short_key) + qrcode.generate_image(content) + qrcode.save() + return show_question(request, question, answerpaper, + course_id=answerpaper.course.id, module_id=module_id, + previous_question=question) + + +def upload_file(request, key): + qrcode = get_object_or_404(QRcode, short_key=key, active=True, used=False) + handler = qrcode.handler + context = {'question' : handler.question, 'key' : qrcode.short_key} + if not handler.can_use(): + context['success'] = True + context['msg'] = 'Sorry, test time up!' + return render(request, 'yaksh/upload_file.html', context) + if request.method == 'POST': + assignment_filename = request.FILES.getlist('assignment') + if not assignment_filename: + msg = 'Please upload assignment file' + context['msg'] = msg + return render(request, 'yaksh/upload_file.html', context) + for fname in assignment_filename: + fname._name = fname._name.replace(" ", "_") + assignment_files = AssignmentUpload.objects.filter( + assignmentQuestion=handler.question, + course_id=handler.answerpaper.course.id, + assignmentFile__icontains=fname, user=handler.user, + question_paper=handler.answerpaper.question_paper) + if assignment_files.exists(): + assign_file = assignment_files.first() + if os.path.exists(assign_file.assignmentFile.path): + os.remove(assign_file.assignmentFile.path) + assign_file.delete() + AssignmentUpload.objects.create(user=handler.user, + assignmentQuestion=handler.question, + course_id=handler.answerpaper.course.id, assignmentFile=fname, + question_paper=handler.answerpaper.question_paper) + qrcode.set_used() + qrcode.deactivate() + qrcode.save() + context['success'] = True + msg = "File Uploaded Successfully! Reload the (test)question "\ + "page to see the uploaded file" + context['msg'] = msg + return render(request, 'yaksh/upload_file.html', context) + return render(request, 'yaksh/upload_file.html', context) + |