summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--yaksh/models.py81
-rw-r--r--yaksh/templates/yaksh/question.html9
-rw-r--r--yaksh/templates/yaksh/upload_file.html32
-rw-r--r--yaksh/urls.py4
-rw-r--r--yaksh/views.py75
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)
+