summaryrefslogtreecommitdiff
path: root/testapp/exam
diff options
context:
space:
mode:
Diffstat (limited to 'testapp/exam')
-rw-r--r--testapp/exam/forms.py130
-rw-r--r--testapp/exam/migrations/0001_initial.py193
-rw-r--r--testapp/exam/migrations/__init__.py0
-rw-r--r--testapp/exam/models.py41
-rw-r--r--testapp/exam/urls.py44
-rw-r--r--testapp/exam/views.py802
6 files changed, 892 insertions, 318 deletions
diff --git a/testapp/exam/forms.py b/testapp/exam/forms.py
index a5ca26f..7bbf601 100644
--- a/testapp/exam/forms.py
+++ b/testapp/exam/forms.py
@@ -1,44 +1,57 @@
from django import forms
-from exam.models import Profile
+from exam.models import Profile,Quiz,Question
from django.contrib.auth import authenticate
from django.contrib.auth.models import User
+from taggit.managers import TaggableManager
+from taggit.forms import TagField
+from taggit_autocomplete_modified.managers import TaggableManagerAutocomplete
+from taggit_autocomplete_modified.widgets import TagAutocomplete
+from taggit_autocomplete_modified import settings
from string import letters, punctuation, digits
+import datetime
+
+QUESTION_TYPE_CHOICES = (
+ ("python", "Python"),
+ ("bash", "Bash"),
+ ("mcq", "MCQ"),
+ )
UNAME_CHARS = letters + "._" + digits
PWD_CHARS = letters + punctuation + digits
class UserRegisterForm(forms.Form):
+ """A Class to create new form for User's Registration.
+ It has the various fields and functions required to register
+ a new user to the system"""
- username = forms.CharField(max_length=30,
- help_text='Letters, digits, period and underscores only.')
+ username = forms.CharField\
+ (max_length=30, help_text='Letters, digits,\
+ period and underscores only.')
email = forms.EmailField()
- password = forms.CharField(max_length=30,
- widget=forms.PasswordInput())
- confirm_password = forms.CharField(max_length=30,
- widget=forms.PasswordInput())
+ password = forms.CharField(max_length=30, widget=forms.PasswordInput())
+ confirm_password = forms.CharField\
+ (max_length=30, widget=forms.PasswordInput())
first_name = forms.CharField(max_length=30)
last_name = forms.CharField(max_length=30)
- roll_number = forms.CharField(max_length=30,
- help_text="Use a dummy if you don't have one.")
- institute = forms.CharField(max_length=128,
- help_text='Institute/Organization')
- department = forms.CharField(max_length=64,
- help_text='Department you work/study at')
- position = forms.CharField(max_length=64,
- help_text='Student/Faculty/Researcher/Industry/etc.')
+ roll_number = forms.CharField\
+ (max_length=30, help_text="Use a dummy if you don't have one.")
+ institute = forms.CharField\
+ (max_length=128, help_text='Institute/Organization')
+ department = forms.CharField\
+ (max_length=64, help_text='Department you work/study at')
+ position = forms.CharField\
+ (max_length=64, help_text='Student/Faculty/Researcher/Industry/etc.')
def clean_username(self):
u_name = self.cleaned_data["username"]
-
if u_name.strip(UNAME_CHARS):
msg = "Only letters, digits, period and underscore characters are "\
"allowed in username"
raise forms.ValidationError(msg)
-
try:
- User.objects.get(username__exact = u_name)
+ User.objects.get(username__exact=u_name)
raise forms.ValidationError("Username already exists.")
except User.DoesNotExist:
return u_name
@@ -46,8 +59,8 @@ class UserRegisterForm(forms.Form):
def clean_password(self):
pwd = self.cleaned_data['password']
if pwd.strip(PWD_CHARS):
- raise forms.ValidationError("Only letters, digits and punctuation are \
- allowed in password")
+ raise forms.ValidationError("Only letters, digits and punctuation\
+ are allowed in password")
return pwd
def clean_confirm_password(self):
@@ -80,16 +93,83 @@ class UserRegisterForm(forms.Form):
return u_name, pwd
class UserLoginForm(forms.Form):
- username = forms.CharField(max_length = 30)
+ """Creates a form which will allow the user to log into the system."""
+
+ username = forms.CharField(max_length=30)
password = forms.CharField(max_length=30, widget=forms.PasswordInput())
def clean(self):
super(UserLoginForm, self).clean()
- u_name, pwd = self.cleaned_data["username"], self.cleaned_data["password"]
- user = authenticate(username = u_name, password = pwd)
-
+ try:
+ u_name, pwd = self.cleaned_data["username"],\
+ self.cleaned_data["password"]
+ user = authenticate(username=u_name, password=pwd)
+ except Exception:
+ raise forms.ValidationError\
+ ("Username and/or Password is not entered")
if not user:
raise forms.ValidationError("Invalid username/password")
-
return user
+class QuizForm(forms.Form):
+ """Creates a form to add or edit a Quiz.
+ It has the related fields and functions required."""
+
+ start_date = forms.DateField(initial=datetime.date.today)
+ duration = forms.IntegerField()
+ active = forms.BooleanField(required = False)
+ tags = TagField(widget=TagAutocomplete())
+ description = forms.CharField(max_length=256, widget=forms.Textarea\
+ (attrs={'cols':20,'rows':1}))
+
+ def save(self):
+ start_date = self.cleaned_data["start_date"]
+ duration = self.cleaned_data["duration"]
+ active = self.cleaned_data['active']
+ description = self.cleaned_data["description"]
+
+ new_quiz = Quiz()
+ new_quiz.start_date = start_date
+ new_quiz.duration = duration
+ new_quiz.active = active
+ new_quiz.description = description
+ new_quiz.save()
+
+class QuestionForm(forms.Form):
+ """Creates a form to add or edit a Question.
+ It has the related fields and functions required."""
+
+ summary = forms.CharField(widget=forms.Textarea\
+ (attrs={'cols': 40, 'rows': 1}))
+ description = forms.CharField(widget=forms.Textarea\
+ (attrs={'cols': 40, 'rows': 1}))
+ points = forms.FloatField()
+ test = forms.CharField(widget=forms.Textarea\
+ (attrs={'cols': 40, 'rows': 1}))
+ options = forms.CharField(widget=forms.Textarea\
+ (attrs={'cols': 40, 'rows': 1}),required=False)
+ type = forms.CharField(max_length=8, widget=forms.Select\
+ (choices=QUESTION_TYPE_CHOICES))
+ active = forms.BooleanField(required=False)
+ tags = TagField(widget=TagAutocomplete(),required=False)
+ snippet = forms.CharField(widget=forms.Textarea\
+ (attrs={'cols': 40, 'rows': 1}),required=False)
+
+ def save(self):
+ summary = self.cleaned_data["summary"]
+ description = self.cleaned_data["description"]
+ points = self.cleaned_data['points']
+ test = self.cleaned_data["test"]
+ options = self.cleaned_data['options']
+ type = self.cleaned_data["type"]
+ active = self.cleaned_data["active"]
+
+ new_question = Question()
+ new_question.summary = summary
+ new_question.description = description
+ new_question.points = points
+ new_question.test = test
+ new_question.options = options
+ new_question.type = type
+ new_question.active = active
+ new_question.save()
diff --git a/testapp/exam/migrations/0001_initial.py b/testapp/exam/migrations/0001_initial.py
deleted file mode 100644
index 49048cc..0000000
--- a/testapp/exam/migrations/0001_initial.py
+++ /dev/null
@@ -1,193 +0,0 @@
-# encoding: utf-8
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
-
- # Adding model 'Profile'
- db.create_table('exam_profile', (
- ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('user', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['auth.User'], unique=True)),
- ('roll_number', self.gf('django.db.models.fields.CharField')(max_length=20)),
- ('institute', self.gf('django.db.models.fields.CharField')(max_length=128)),
- ('department', self.gf('django.db.models.fields.CharField')(max_length=64)),
- ('position', self.gf('django.db.models.fields.CharField')(max_length=64)),
- ))
- db.send_create_signal('exam', ['Profile'])
-
- # Adding model 'Question'
- db.create_table('exam_question', (
- ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('summary', self.gf('django.db.models.fields.CharField')(max_length=256)),
- ('description', self.gf('django.db.models.fields.TextField')()),
- ('points', self.gf('django.db.models.fields.FloatField')(default=1.0)),
- ('test', self.gf('django.db.models.fields.TextField')(blank=True)),
- ('options', self.gf('django.db.models.fields.TextField')(blank=True)),
- ('type', self.gf('django.db.models.fields.CharField')(max_length=24)),
- ('active', self.gf('django.db.models.fields.BooleanField')(default=True)),
- ))
- db.send_create_signal('exam', ['Question'])
-
- # Adding model 'Answer'
- db.create_table('exam_answer', (
- ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('question', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['exam.Question'])),
- ('answer', self.gf('django.db.models.fields.TextField')()),
- ('error', self.gf('django.db.models.fields.TextField')()),
- ('marks', self.gf('django.db.models.fields.FloatField')(default=0.0)),
- ('correct', self.gf('django.db.models.fields.BooleanField')(default=False)),
- ))
- db.send_create_signal('exam', ['Answer'])
-
- # Adding model 'Quiz'
- db.create_table('exam_quiz', (
- ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('start_date', self.gf('django.db.models.fields.DateField')()),
- ('duration', self.gf('django.db.models.fields.IntegerField')(default=20)),
- ('active', self.gf('django.db.models.fields.BooleanField')(default=True)),
- ('description', self.gf('django.db.models.fields.CharField')(max_length=256)),
- ))
- db.send_create_signal('exam', ['Quiz'])
-
- # Adding model 'QuestionPaper'
- db.create_table('exam_questionpaper', (
- ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])),
- ('profile', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['exam.Profile'])),
- ('quiz', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['exam.Quiz'])),
- ('start_time', self.gf('django.db.models.fields.DateTimeField')()),
- ('user_ip', self.gf('django.db.models.fields.CharField')(max_length=15)),
- ('key', self.gf('django.db.models.fields.CharField')(max_length=10)),
- ('active', self.gf('django.db.models.fields.BooleanField')(default=True)),
- ('questions', self.gf('django.db.models.fields.CharField')(max_length=128)),
- ('questions_answered', self.gf('django.db.models.fields.CharField')(max_length=128)),
- ('comments', self.gf('django.db.models.fields.TextField')()),
- ))
- db.send_create_signal('exam', ['QuestionPaper'])
-
- # Adding M2M table for field answers on 'QuestionPaper'
- db.create_table('exam_questionpaper_answers', (
- ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
- ('questionpaper', models.ForeignKey(orm['exam.questionpaper'], null=False)),
- ('answer', models.ForeignKey(orm['exam.answer'], null=False))
- ))
- db.create_unique('exam_questionpaper_answers', ['questionpaper_id', 'answer_id'])
-
-
- def backwards(self, orm):
-
- # Deleting model 'Profile'
- db.delete_table('exam_profile')
-
- # Deleting model 'Question'
- db.delete_table('exam_question')
-
- # Deleting model 'Answer'
- db.delete_table('exam_answer')
-
- # Deleting model 'Quiz'
- db.delete_table('exam_quiz')
-
- # Deleting model 'QuestionPaper'
- db.delete_table('exam_questionpaper')
-
- # Removing M2M table for field answers on 'QuestionPaper'
- db.delete_table('exam_questionpaper_answers')
-
-
- models = {
- 'auth.group': {
- 'Meta': {'object_name': 'Group'},
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
- 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
- },
- 'auth.permission': {
- 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
- 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
- },
- 'auth.user': {
- 'Meta': {'object_name': 'User'},
- 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
- 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
- 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
- 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
- },
- 'contenttypes.contenttype': {
- 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
- 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- 'exam.answer': {
- 'Meta': {'object_name': 'Answer'},
- 'answer': ('django.db.models.fields.TextField', [], {}),
- 'correct': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'error': ('django.db.models.fields.TextField', [], {}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'marks': ('django.db.models.fields.FloatField', [], {'default': '0.0'}),
- 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['exam.Question']"})
- },
- 'exam.profile': {
- 'Meta': {'object_name': 'Profile'},
- 'department': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'institute': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'position': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
- 'roll_number': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
- 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'})
- },
- 'exam.question': {
- 'Meta': {'object_name': 'Question'},
- 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'description': ('django.db.models.fields.TextField', [], {}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'options': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'points': ('django.db.models.fields.FloatField', [], {'default': '1.0'}),
- 'summary': ('django.db.models.fields.CharField', [], {'max_length': '256'}),
- 'test': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'type': ('django.db.models.fields.CharField', [], {'max_length': '24'})
- },
- 'exam.questionpaper': {
- 'Meta': {'object_name': 'QuestionPaper'},
- 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'answers': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['exam.Answer']", 'symmetrical': 'False'}),
- 'comments': ('django.db.models.fields.TextField', [], {}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'key': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
- 'profile': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['exam.Profile']"}),
- 'questions': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'questions_answered': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'quiz': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['exam.Quiz']"}),
- 'start_time': ('django.db.models.fields.DateTimeField', [], {}),
- 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
- 'user_ip': ('django.db.models.fields.CharField', [], {'max_length': '15'})
- },
- 'exam.quiz': {
- 'Meta': {'object_name': 'Quiz'},
- 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '256'}),
- 'duration': ('django.db.models.fields.IntegerField', [], {'default': '20'}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'start_date': ('django.db.models.fields.DateField', [], {})
- }
- }
-
- complete_apps = ['exam']
diff --git a/testapp/exam/migrations/__init__.py b/testapp/exam/migrations/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/testapp/exam/migrations/__init__.py
+++ /dev/null
diff --git a/testapp/exam/models.py b/testapp/exam/models.py
index 717e02e..00d32e4 100644
--- a/testapp/exam/models.py
+++ b/testapp/exam/models.py
@@ -1,7 +1,9 @@
import datetime
from django.db import models
from django.contrib.auth.models import User
-
+from taggit_autocomplete_modified.managers import TaggableManagerAutocomplete\
+as TaggableManager
+from django.http import HttpResponse
################################################################################
class Profile(models.Model):
"""Profile for a user to store roll number and other details."""
@@ -43,6 +45,12 @@ class Question(models.Model):
# Is this question active or not. If it is inactive it will not be used
# when creating a QuestionPaper.
active = models.BooleanField(default=True)
+
+ #Code Snippet
+ snippet = models.CharField(max_length=256)
+
+ #Tags for the Question.
+ tags = TaggableManager()
def __unicode__(self):
return self.summary
@@ -89,6 +97,10 @@ class Quiz(models.Model):
# Description of quiz.
description = models.CharField(max_length=256)
+
+ #Tags for the Quiz.
+ tags = TaggableManager()
+
class Meta:
verbose_name_plural = "Quizzes"
@@ -97,9 +109,13 @@ class Quiz(models.Model):
desc = self.description or 'Quiz'
return '%s: on %s for %d minutes'%(desc, self.start_date, self.duration)
-
################################################################################
class QuestionPaper(models.Model):
+ quiz = models.ForeignKey(Quiz)
+ questions = models.ManyToManyField(Question)
+
+################################################################################
+class AnswerPaper(models.Model):
"""A question paper for a student -- one per student typically.
"""
# The user taking this question paper.
@@ -108,23 +124,22 @@ class QuestionPaper(models.Model):
# The user's profile, we store a reference to make it easier to access the
# data.
profile = models.ForeignKey(Profile)
-
+
+ # All questions that remains to attempt to perticular Student
+ questions = models.CharField(max_length=128)
+
# The Quiz to which this question paper is attached to.
- quiz = models.ForeignKey(Quiz)
+ question_paper = models.ForeignKey(QuestionPaper)
# The time when this paper was started by the user.
start_time = models.DateTimeField()
+
+ # The time when this paper was ended by the user.
+ end_time = models.DateTimeField()
# User's IP which is logged.
user_ip = models.CharField(max_length=15)
- # Unused currently.
- key = models.CharField(max_length=10)
- # used to allow/stop a user from retaking the question paper.
- active = models.BooleanField(default = True)
-
- # The questions (a list of ids separated by '|')
- questions = models.CharField(max_length=128)
# The questions successfully answered (a list of ids separated by '|')
questions_answered = models.CharField(max_length=128)
@@ -152,7 +167,7 @@ class QuestionPaper(models.Model):
def completed_question(self, question_id):
"""Removes the question from the list of questions and returns
- the next."""
+the next."""
qa = self.questions_answered
if len(qa) > 0:
self.questions_answered = '|'.join([qa, str(question_id)])
@@ -188,7 +203,7 @@ class QuestionPaper(models.Model):
except AttributeError:
# total_seconds is new in Python 2.7. :(
secs = dt.seconds + dt.days*24*3600
- total = self.quiz.duration*60.0
+ total = self.question_paper.quiz.duration*60.0
remain = max(total - secs, 0)
return int(remain)
diff --git a/testapp/exam/urls.py b/testapp/exam/urls.py
index 34e329f..b3cfceb 100644
--- a/testapp/exam/urls.py
+++ b/testapp/exam/urls.py
@@ -3,14 +3,44 @@ from django.conf.urls.defaults import patterns, include, url
urlpatterns = patterns('exam.views',
url(r'^$', 'index'),
url(r'^login/$', 'user_login'),
- url(r'^register/$', 'user_register'),
+ url(r'^quizzes/$','quizlist_user'),
+ url(r'^results/$','results_user'),
url(r'^start/$', 'start'),
- url(r'^quit/$', 'quit'),
- url(r'^complete/$', 'complete'),
- url(r'^monitor/$', 'monitor'),
- url(r'^monitor/(?P<quiz_id>\d+)/$', 'monitor'),
- url(r'^user_data/(?P<username>[a-zA-Z0-9_.]+)/$', 'user_data'),
- url(r'^grade_user/(?P<username>[a-zA-Z0-9_.]+)/$', 'grade_user'),
+ url(r'^start/(?P<questionpaper_id>\d+)/$','start'),
+ url(r'^quit/(?P<answerpaper_id>\d+)/$', 'quit'),
+ url(r'^intro/$','start'),
+ url(r'^complete/$', 'complete'),
+ url(r'^complete/(?P<answerpaper_id>\d+)/$', 'complete'),
+ url(r'^register/$', 'user_register'),
url(r'^(?P<q_id>\d+)/$', 'question'),
url(r'^(?P<q_id>\d+)/check/$', 'check'),
+ url(r'^(?P<q_id>\d+)/check/(?P<questionpaper_id>\d+)/$', 'check'),
+
+
+ url(r'^manage/$', 'prof_manage'),
+ url(r'^manage/addquestion/$', 'add_question'),
+ url(r'^manage/addquestion/(?P<question_id>\d+)/$', 'add_question'),
+ url(r'^manage/addquiz/$', 'add_quiz'),
+ url(r'^manage/editquiz/$', 'edit_quiz'),
+ url(r'^manage/editquestion/$', 'edit_question'),
+ url(r'^manage/addquiz/(?P<quiz_id>\d+)/$', 'add_quiz'),
+ url(r'^manage/gradeuser/$', 'show_all_users'),
+ url(r'^manage/gradeuser/(?P<username>[a-zA-Z0-9_.]+)/$', 'grade_user'),
+ url(r'^manage/questions/$', 'show_all_questions'),
+ url(r'^manage/showquiz/$','show_all_quiz'),
+ url(r'^manage/monitor/$', 'monitor'),
+ url(r'^manage/showquestionpapers/$','show_all_questionpapers'),
+ url(r'^manage/showquestionpapers/(?P<questionpaper_id>\d+)/$',\
+ 'show_all_questionpapers'),
+ url(r'^manage/monitor/(?P<quiz_id>\d+)/$', 'monitor'),
+ url(r'^manage/user_data/(?P<username>[a-zA-Z0-9_.]+)/$','user_data'),
+ url(r'^manage/designquestionpaper/$','design_questionpaper'),
+ url(r'^manage/designquestionpaper/(?P<questionpaper_id>\d+)/$',\
+ 'design_questionpaper'),
+ url(r'^manage/designquestionpaper/automatic/(?P<questionpaper_id>\d+)/$',\
+ 'automatic_questionpaper'),
+ url(r'^manage/designquestionpaper/automatic$','automatic_questionpaper'),
+ url(r'^manage/designquestionpaper/manual$','manual_questionpaper'),
+ url(r'^manage/designquestionpaper/manual/(?P<questionpaper_id>\d+)/$',\
+ 'manual_questionpaper'),
)
diff --git a/testapp/exam/views.py b/testapp/exam/views.py
index c178a0b..5a5f5fe 100644
--- a/testapp/exam/views.py
+++ b/testapp/exam/views.py
@@ -5,15 +5,18 @@ import stat
from os.path import dirname, pardir, abspath, join, exists
import datetime
+from django.http import HttpResponse
from django.contrib.auth import login, logout, authenticate
from django.shortcuts import render_to_response, get_object_or_404, redirect
from django.template import RequestContext
from django.http import Http404
from django.db.models import Sum
-
+from taggit.models import Tag
+from itertools import chain
# Local imports.
-from exam.models import Quiz, Question, QuestionPaper, Profile, Answer, User
-from exam.forms import UserRegisterForm, UserLoginForm
+from exam.models import Quiz, Question, QuestionPaper
+from exam.models import Profile, Answer, AnswerPaper, User
+from exam.forms import UserRegisterForm, UserLoginForm, QuizForm, QuestionForm
from exam.xmlrpc_clients import code_server
from settings import URL_ROOT
@@ -22,10 +25,11 @@ OUTPUT_DIR = abspath(join(dirname(__file__), pardir, 'output'))
def my_redirect(url):
- """An overridden redirect to deal with URL_ROOT-ing. See settings.py
- for details."""
+ """An overridden redirect to deal with URL_ROOT-ing. See settings.py
+for details."""
return redirect(URL_ROOT + url)
+
def my_render_to_response(template, context=None, **kwargs):
"""Overridden render_to_response.
"""
@@ -33,34 +37,74 @@ def my_render_to_response(template, context=None, **kwargs):
context = {'URL_ROOT': URL_ROOT}
else:
context['URL_ROOT'] = URL_ROOT
- return render_to_response(template, context, **kwargs)
+ return render_to_response(template, context, **kwargs)
def gen_key(no_of_chars):
"""Generate a random key of the number of characters."""
allowed_chars = string.digits+string.uppercase
return ''.join([random.choice(allowed_chars) for i in range(no_of_chars)])
-
+
+
def get_user_dir(user):
"""Return the output directory for the user."""
+
user_dir = join(OUTPUT_DIR, str(user.username))
if not exists(user_dir):
os.mkdir(user_dir)
- # Make it rwx by others.
- os.chmod(user_dir, stat.S_IROTH | stat.S_IWOTH | stat.S_IXOTH \
- | stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR \
+ # Make it rwx by others.
+ os.chmod(user_dir, stat.S_IROTH | stat.S_IWOTH | stat.S_IXOTH\
+ | stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR\
| stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP)
return user_dir
-
+
+
+def is_moderator(user):
+ """Check if the user is having moderator rights"""
+ if user.groups.filter(name='moderator').count() == 1:
+ return True
+
+
+def fetch_questions(request):
+ """Fetch questions from database based on the given search conditions &
+ tags"""
+ set1 = set()
+ set2 = set()
+ first_tag = request.POST.get('first_tag')
+ first_condition = request.POST.get('first_condition')
+ second_tag = request.POST.get('second_tag')
+ second_condition = request.POST.get('second_condition')
+ third_tag = request.POST.get('third_tag')
+ question1 = set(Question.objects.filter(tags__name__in=[first_tag]))
+ question2 = set(Question.objects.filter(tags__name__in=[second_tag]))
+ question3 = set(Question.objects.filter(tags__name__in=[third_tag]))
+ if first_condition == 'and':
+ set1 = question1.intersection(question2)
+ if second_condition == 'and':
+ set2 = set1.intersection(question3)
+ else:
+ set2 = set1.union(question3)
+ else:
+ set1 = question1.union(question2)
+ if second_condition == 'and':
+ set2 = set1.intersection(question3)
+ else:
+ set2 = set1.union(question3)
+ return set2
+
+
def index(request):
"""The start page.
"""
user = request.user
if user.is_authenticated():
+ if user.groups.filter(name='moderator').count() > 0:
+ return my_redirect('/exam/manage/')
return my_redirect("/exam/start/")
return my_redirect("/exam/login/")
+
def user_register(request):
""" Register a new user.
Create a user and corresponding profile and store roll_number also."""
@@ -74,34 +118,465 @@ def user_register(request):
if form.is_valid():
data = form.cleaned_data
u_name, pwd = form.save()
-
- new_user = authenticate(username = u_name, password = pwd)
+ new_user = authenticate(username=u_name, password=pwd)
login(request, new_user)
return my_redirect("/exam/start/")
-
else:
return my_render_to_response('exam/register.html',
- {'form':form},
+ {'form': form},
context_instance=RequestContext(request))
else:
form = UserRegisterForm()
return my_render_to_response('exam/register.html',
- {'form':form},
+ {'form': form}, context_instance=RequestContext(request))
+
+
+def quizlist_user(request):
+ """Show All Quizzes that is available to logged-in user."""
+ user = request.user
+ avail_quiz = list(QuestionPaper.objects.filter(quiz__active=True))
+ user_answerpapers = AnswerPaper.objects.filter(user=user)
+ user_quiz = []
+
+ if user_answerpapers.count() == 0:
+ context = {'quizzes': avail_quiz}
+ return my_render_to_response("exam/quizzes_user.html", context)
+
+ for paper in user_answerpapers:
+ for quiz in avail_quiz:
+ if paper.question_paper.id == quiz.id and \
+ paper.end_time != paper.start_time:
+ avail_quiz.remove(quiz)
+
+ context = {'quizzes': avail_quiz, 'user': user}
+ return my_render_to_response("exam/quizzes_user.html", context)
+
+
+def results_user(request):
+ """Show list of Results of Quizzes that is taken by logged-in user."""
+ user = request.user
+ papers = AnswerPaper.objects.filter(user=user)
+ quiz_marks = []
+ for paper in papers:
+ temp = paper.question_paper.quiz.description, paper.get_total_marks()
+ quiz_marks.append(temp)
+ context = {'papers': quiz_marks}
+ return my_render_to_response("exam/results_user.html", context)
+
+
+def edit_quiz(request):
+ """Edit the list of quizzes seleted by the user for editing."""
+
+ user = request.user
+ if not user.is_authenticated() or not is_moderator(user):
+ raise Http404('You are not allowed to view this page!')
+ quiz_list = request.POST.getlist('quizzes')
+ start_date = request.POST.getlist('start_date')
+ duration = request.POST.getlist('duration')
+ active = request.POST.getlist('active')
+ description = request.POST.getlist('description')
+ tags = request.POST.getlist('tags')
+
+ for j, quiz_id in enumerate(quiz_list):
+ quiz = Quiz.objects.get(id=quiz_id)
+ quiz.start_date = start_date[j]
+ quiz.duration = duration[j]
+ quiz.active = active[j]
+ quiz.description = description[j]
+ quiz.save()
+ edit_tags = tags[j]
+ quiz.save()
+ for tag in quiz.tags.all():
+ quiz.tags.remove(tag)
+ tags_split = edit_tags.split(', ')
+ for i in range(0, len(tags_split)-1):
+ tag = tags_split[i].strip()
+ quiz.tags.add(tag)
+ return my_redirect("/exam/manage/showquiz/")
+
+
+def edit_question(request):
+ """Edit the list of questions seleted by the user for editing."""
+ user = request.user
+ if not user.is_authenticated() or not is_moderator(user):
+ raise Http404('You are not allowed to view this page!')
+
+ question_list = request.POST.getlist('questions')
+ summary = request.POST.getlist('summary')
+ description = request.POST.getlist('description')
+ points = request.POST.getlist('points')
+ test = request.POST.getlist('test')
+ options = request.POST.getlist('options')
+ type = request.POST.getlist('type')
+ active = request.POST.getlist('active')
+ snippet = request.POST.getlist('snippet')
+ tags = request.POST.getlist('tags')
+ for j, question_id in enumerate(question_list):
+ question = Question.objects.get(id=question_id)
+ question.summary = summary[j]
+ question.description = description[j]
+ question.points = points[j]
+ question.test = test[j]
+ question.options = options[j]
+ question.type = type[j]
+ edit_tags = tags[j]
+ question.active = active[j]
+ question.snippet = snippet[j]
+ question.save()
+ for tag in question.tags.all():
+ question.tags.remove(tag)
+ tags_split = edit_tags.split(',')
+ for i in range(0, len(tags_split)-1):
+ tag = tags_split[i].strip()
+ question.tags.add(tag)
+ return my_redirect("/exam/manage/questions")
+
+
+def add_question(request, question_id=None):
+ """To add a new question in the database.
+ Create a new question and store it."""
+ user = request.user
+ if not user.is_authenticated() or not is_moderator(user):
+ raise Http404('You are not allowed to view this page!')
+ if request.method == "POST":
+ form = QuestionForm(request.POST)
+ if form.is_valid():
+ data = form.cleaned_data
+ if question_id is None:
+ form.save()
+ question = Question.objects.order_by("-id")[0]
+ tags = form['tags'].data.split(',')
+ for i in range(0, len(tags)-1):
+ tag = tags[i].strip()
+ question.tags.add(tag)
+ return my_redirect("/exam/manage/questions")
+ else:
+ d = Question.objects.get(id=question_id)
+ d.summary = form['summary'].data
+ d.description = form['description'].data
+ d.points = form['points'].data
+ d.test = form['test'].data
+ d.options = form['options'].data
+ d.type = form['type'].data
+ d.active = form['active'].data
+ d.snippet = form['snippet'].data
+ d.save()
+ question = Question.objects.get(id=question_id)
+ for tag in question.tags.all():
+ question.tags.remove(tag)
+ tags = form['tags'].data.split(', ')
+ for i in range(0, len(tags)-1):
+ tag = tags[i].strip()
+ question.tags.add(tag)
+ return my_redirect("/exam/manage/questions")
+ else:
+ return my_render_to_response('exam/add_question.html',
+ {'form': form}, context_instance=RequestContext(request))
+ else:
+ if question_id is None:
+ form = QuestionForm()
+ return my_render_to_response('exam/add_question.html',
+ {'form': form}, context_instance=RequestContext(request))
+ else:
+ d = Question.objects.get(id=question_id)
+ form = QuestionForm()
+ form.initial['summary'] = d.summary
+ form.initial['description'] = d.description
+ form.initial['points'] = d.points
+ form.initial['test'] = d.test
+ form.initial['options'] = d.options
+ form.initial['type'] = d.type
+ form.initial['active'] = d.active
+ form.initial['snippet'] = d.snippet
+ form_tags = d.tags.all()
+ form_tags_split = form_tags.values('name')
+ initial_tags = ""
+ for tag in form_tags_split:
+ initial_tags = initial_tags + str(tag['name']).strip() + ","
+ if (initial_tags == ","):
+ initial_tags = ""
+ form.initial['tags'] = initial_tags
+ return my_render_to_response('exam/add_question.html',
+ {'form': form},
+ context_instance=RequestContext(request))
+
+
+def add_quiz(request, quiz_id=None):
+ """To add a new quiz in the database.
+ Create a new question and store it."""
+
+ user = request.user
+ if not user.is_authenticated() or not is_moderator(user):
+ raise Http404('You are not allowed to view this page!')
+ if request.method == "POST":
+ form = QuizForm(request.POST)
+ if form.is_valid():
+ data = form.cleaned_data
+ if quiz_id is None:
+ form.save()
+ quiz = Quiz.objects.order_by("-id")[0]
+ tags = form['tags'].data.split(',')
+ for tag in tags:
+ tag = tag.strip()
+ quiz.tags.add(tag)
+ return my_redirect("/exam/manage/designquestionpaper")
+ else:
+ d = Quiz.objects.get(id=quiz_id)
+ d.start_date = form['start_date'].data
+ d.duration = form['duration'].data
+ d.active = form['active'].data
+ d.description = form['description'].data
+ d.save()
+ quiz = Quiz.objects.get(id=quiz_id)
+ for tag in quiz.tags.all():
+ quiz.tags.remove(tag)
+ tags = form['tags'].data.split(',')
+ for i in range(0, len(tags)-1):
+ tag = tags[i].strip()
+ quiz.tags.add(tag)
+ return my_redirect("/exam/manage/showquiz")
+ else:
+ return my_render_to_response('exam/add_quiz.html',
+ {'form': form},
+ context_instance=RequestContext(request))
+ else:
+ if quiz_id is None:
+ form = QuizForm()
+ return my_render_to_response('exam/add_quiz.html',
+ {'form': form},
context_instance=RequestContext(request))
+ else:
+ d = Quiz.objects.get(id=quiz_id)
+ form = QuizForm()
+ form.initial['start_date'] = d.start_date
+ form.initial['duration'] = d.duration
+ form.initial['description'] = d.description
+ form.initial['active'] = d.active
+ form_tags = d.tags.all()
+ form_tags_split = form_tags.values('name')
+ initial_tags = ""
+ for tag in form_tags_split:
+ initial_tags = initial_tags + str(tag['name']).strip() + ","
+ if (initial_tags == ","):
+ initial_tags = ""
+ form.initial['tags'] = initial_tags
+ return my_render_to_response('exam/add_quiz.html',
+ {'form': form},
+ context_instance=RequestContext(request))
+
+
+def design_questionpaper(request, questionpaper_id=None):
+ user = request.user
+ if not user.is_authenticated() or not is_moderator(user):
+ raise Http404('You are not allowed to view this page!')
+ return my_render_to_response('exam/add_questionpaper.html', {},
+ context_instance=RequestContext(request))
+
+
+def show_all_questionpapers(request, questionpaper_id=None):
+ user = request.user
+ if not user.is_authenticated() or not is_moderator(user):
+ raise Http404('You are not allowed to view this page!')
+
+ if request.method == "POST" and request.POST.get('add') == "add":
+ return my_redirect("/exam/manage/designquestionpaper/" + \
+ questionpaper_id)
+
+ if request.method == "POST" and request.POST.get('delete') == "delete":
+ data = request.POST.getlist('papers')
+ q_paper = QuestionPaper.objects.get(id=questionpaper_id)
+ for i in data:
+ q_paper.questions.remove(Question.objects.get(id=i))
+ question_paper = QuestionPaper.objects.all()
+ context = {'papers': question_paper}
+ return my_render_to_response('exam/showquestionpapers.html', context,
+ context_instance=RequestContext(request))
+ if questionpaper_id is None:
+ qu_papers = QuestionPaper.objects.all()
+ context = {'papers': qu_papers}
+ return my_render_to_response('exam/showquestionpapers.html', context,
+ context_instance=RequestContext(request))
+ else:
+ qu_papers = QuestionPaper.objects.get(id=questionpaper_id)
+ quiz = qu_papers.quiz
+ questions = qu_papers.questions.all()
+ context = {'papers': {'quiz': quiz, 'questions': questions}}
+ return my_render_to_response('exam/editquestionpaper.html', context,
+ context_instance=RequestContext(request))
+
+
+def automatic_questionpaper(request, questionpaper_id=None):
+ """Generate automatic question paper for a particular quiz"""
+
+ user = request.user
+ if not user.is_authenticated() or not is_moderator(user):
+ raise Http404('You are not allowed to view this page!')
+
+ if questionpaper_id is None:
+ if request.method == "POST":
+ if request.POST.get('save') == 'save':
+ quiz = Quiz.objects.order_by("-id")[0]
+ quest_paper = QuestionPaper()
+ quest_paper.quiz = quiz
+ quest_paper.save()
+ questions = request.POST.getlist('questions')
+ for i in questions:
+ if i.isdigit():
+ q = Question.objects.get(id=i)
+ quest_paper.questions.add(q)
+ return my_redirect('/exam/manage/showquiz')
+ else:
+ no_questions = int(request.POST.get('questions'))
+ fetched_questions = fetch_questions(request)
+ n = len(fetched_questions)
+ msg = ''
+ if (no_questions < n):
+ i = n - no_questions
+ for i in range(0, i):
+ fetched_questions.pop()
+ elif (no_questions > n):
+ msg = 'The given Criteria does not satisfy the number\
+ of Questions...'
+ tags = Tag.objects.all()
+ context = {'data': {'questions': fetched_questions,
+ 'tags': tags,
+ 'msg': msg}}
+ return my_render_to_response(\
+ 'exam/automatic_questionpaper.html', context,
+ context_instance=RequestContext(request))
+ else:
+ tags = Tag.objects.all()
+ context = {'data': {'tags': tags}}
+ return my_render_to_response('exam/automatic_questionpaper.html',
+ context, context_instance=RequestContext(request))
+
+ else:
+ if request.method == "POST":
+ if request.POST.get('save') == 'save':
+ quest_paper = QuestionPaper.objects.get(id=questionpaper_id)
+ questions = request.POST.getlist('questions')
+ for i in questions:
+ if i.isdigit():
+ q = Question.objects.get(id=i)
+ quest_paper.questions.add(q)
+ return my_redirect('/exam/manage/showquiz')
+ else:
+ no_questions = int(request.POST.get('questions'))
+ fetched_questions = fetch_questions(request)
+ n = len(fetched_questions)
+ msg = ''
+ if(no_questions < n):
+ i = n - no_questions
+ for i in range(0, i):
+ fetched_questions.pop()
+ elif(no_questions > n):
+ msg = 'The given Criteria does not satisfy the number of \
+ Questions...'
+ tags = Tag.objects.all()
+ context = {'data': {'questions': fetched_questions,
+ 'tags': tags,
+ 'msg': msg}}
+ return my_render_to_response\(
+ 'exam/automatic_questionpaper.html', context,
+ context_instance=RequestContext(request))
+ else:
+ tags = Tag.objects.all()
+ context = {'data': {'tags': tags}}
+ return my_render_to_response('exam/automatic_questionpaper.html',
+ context, context_instance=RequestContext(request))
+
+
+def manual_questionpaper(request, questionpaper_id=None):
+ user = request.user
+ if not user.is_authenticated() or not is_moderator(user):
+ raise Http404('You are not allowed to view this page!')
+
+ if questionpaper_id is None:
+ if request.method == "POST":
+ if request.POST.get('save') == 'save':
+ questions = request.POST.getlist('questions')
+ quiz = Quiz.objects.order_by("-id")[0]
+ quest_paper = QuestionPaper()
+ quest_paper.quiz = quiz
+ quest_paper.save()
+ for i in questions:
+ q = Question.objects.get(id=i)
+ quest_paper.questions.add(q)
+ return my_redirect('/exam/manage/showquiz')
+ else:
+ fetched_questions = fetch_questions(request)
+ n = len(fetched_questions)
+ msg = ''
+ if (n == 0):
+ msg = 'No matching Question found...'
+ tags = Tag.objects.all()
+ context = {'data': {'questions': fetched_questions,\
+ 'tags': tags, 'msg': msg}}
+ return my_render_to_response('exam/manual_questionpaper.html',
+ context,
+ context_instance=RequestContext(request))
+ else:
+ tags = Tag.objects.all()
+ context = {'data': {'tags': tags}}
+ return my_render_to_response('exam/manual_questionpaper.html',
+ context, context_instance=RequestContext(request))
+
+ else:
+ if request.method == "POST":
+ if request.POST.get('save') == 'save':
+ quest_paper = QuestionPaper.objects.get(id=questionpaper_id)
+ questions = request.POST.getlist('questions')
+ for i in questions:
+ q = Question.objects.get(id=i)
+ quest_paper.questions.add(q)
+ return my_redirect('/exam/manage/showquiz')
+ else:
+ fetched_questions = fetch_questions(request)
+ n = len(fetched_questions)
+ msg = ''
+ if (n == 0):
+ msg = 'No matching Question found...'
+ tags = Tag.objects.all()
+ context = {'data': {'questions': fetched_questions,\
+ 'tags': tags, 'msg': msg}}
+ return my_render_to_response('exam/manual_questionpaper.html',
+ context,
+ context_instance=RequestContext(request))
+ else:
+ tags = Tag.objects.all()
+ context = {'data': {'tags': tags}}
+ return my_render_to_response('exam/manual_questionpaper.html',
+ context, context_instance=RequestContext(request))
+
+
+def prof_manage(request):
+ """Take credentials of the user with professor/moderator
+ rights/permissions and log in."""
+ user = request.user
+ if user.is_authenticated()\
+ and user.groups.filter(name='moderator').count() > 0:
+ context = {'user': user}
+ return my_render_to_response('manage.html', context)
+ return my_redirect('/exam/login/')
+
def user_login(request):
"""Take the credentials of the user and log the user in."""
user = request.user
if user.is_authenticated():
- return my_redirect("/exam/start/")
+ if user.groups.filter(name='moderator').count() > 0:
+ return my_redirect('/exam/manage/')
+ return my_redirect("/exam/intro/")
if request.method == "POST":
form = UserLoginForm(request.POST)
if form.is_valid():
user = form.cleaned_data
login(request, user)
- return my_redirect("/exam/start/")
+ if user.groups.filter(name='moderator').count() > 0:
+ return my_redirect('/exam/manage/')
+ return my_redirect('/exam/login/')
else:
context = {"form": form}
return my_render_to_response('exam/login.html', context,
@@ -112,21 +587,28 @@ def user_login(request):
return my_render_to_response('exam/login.html', context,
context_instance=RequestContext(request))
-def start(request):
+
+def start(request, questionpaper_id=None):
+ """Check the user cedentials and if any quiz is available,
+ start the exam."""
user = request.user
+ if questionpaper_id is None:
+ return my_redirect('/exam/quizzes/')
try:
- # Right now the app is designed so there is only one active quiz
- # at a particular time.
- quiz = Quiz.objects.get(active=True)
- except Quiz.DoesNotExist:
- msg = 'No active quiz found, please contact your '\
- 'instructor/administrator. Please login again thereafter.'
+ """Right now the app is designed so there is only one active quiz
+ at a particular time."""
+ questionpaper = QuestionPaper.objects.get(id=questionpaper_id)
+ except QuestionPaper.DoesNotExist:
+ msg = 'Quiz not found, please contact your '\
+ 'instructor/administrator. Please login again thereafter.'
return complete(request, reason=msg)
+
try:
- old_paper = QuestionPaper.objects.get(user=user, quiz=quiz)
+ old_paper = AnswerPaper.objects.get(\
+ question_paper=questionpaper, user=user)
q = old_paper.current_question()
- return show_question(request, q)
- except QuestionPaper.DoesNotExist:
+ return show_question(request, q, questionpaper_id)
+ except AnswerPaper.DoesNotExist:
ip = request.META['REMOTE_ADDR']
key = gen_key(10)
try:
@@ -135,68 +617,78 @@ def start(request):
msg = 'You do not have a profile and cannot take the quiz!'
raise Http404(msg)
- new_paper = QuestionPaper(user=user, user_ip=ip, key=key,
- quiz=quiz, profile=profile)
+ new_paper = AnswerPaper(user=user, user_ip=ip,
+ question_paper=questionpaper, profile=profile)
new_paper.start_time = datetime.datetime.now()
-
+ new_paper.end_time = datetime.datetime.now()
# Make user directory.
user_dir = get_user_dir(user)
- questions = [ str(_.id) for _ in Question.objects.filter(active=True) ]
+ questions = [str(_.id) for _ in questionpaper.questions.all()]
random.shuffle(questions)
-
+
+ #questions = questionpaper.questions
+ #random.shuffle(questions)
new_paper.questions = "|".join(questions)
new_paper.save()
-
- # Show the user the intro page.
- context = {'user': user}
+ # Show the user the intro page.
+ context = {'user': user, 'paper_id': questionpaper_id}
ci = RequestContext(request)
- return my_render_to_response('exam/intro.html', context,
- context_instance=ci)
+ return my_render_to_response('exam/intro.html', context,
+ context_instance=ci)
+
+
+def question(request, q_id, questionpaper_id):
+ """Check the credentials of the user and start the exam."""
-def question(request, q_id):
user = request.user
if not user.is_authenticated():
return my_redirect('/exam/login/')
q = get_object_or_404(Question, pk=q_id)
try:
- paper = QuestionPaper.objects.get(user=request.user, quiz__active=True)
- except QuestionPaper.DoesNotExist:
- return my_redirect('/exam/start')
- if not paper.quiz.active:
+ q_paper = QuestionPaper.objects.get(id=questionpaper_id)
+ paper = AnswerPaper.objects.get(\
+ user=request.user, question_paper=q_paper)
+ except AnswerPaper.DoesNotExist:
+ return my_redirect('/exam/start/')
+ if not paper.question_paper.quiz.active:
return complete(request, reason='The quiz has been deactivated!')
time_left = paper.time_left()
if time_left == 0:
return complete(request, reason='Your time is up!')
- quiz_name = paper.quiz.description
- context = {'question': q, 'paper': paper, 'user': user,
- 'quiz_name': quiz_name,
+ quiz_name = paper.question_paper.quiz.description
+ context = {'question': q, 'paper': paper, 'user': user,
+ 'quiz_name': quiz_name,
'time_left': time_left}
ci = RequestContext(request)
return my_render_to_response('exam/question.html', context,
- context_instance=ci)
+ context_instance=ci)
+
-def show_question(request, q_id):
+def show_question(request, q_id, questionpaper_id):
"""Show a question if possible."""
if len(q_id) == 0:
msg = 'Congratulations! You have successfully completed the quiz.'
return complete(request, msg)
else:
- return question(request, q_id)
+ return question(request, q_id, questionpaper_id)
+
+
+def check(request, q_id, questionpaper_id=None):
+ """Checks the answers of the user for particular question"""
-def check(request, q_id):
user = request.user
if not user.is_authenticated():
return my_redirect('/exam/login/')
question = get_object_or_404(Question, pk=q_id)
- paper = QuestionPaper.objects.get(user=user, quiz__active=True)
+ q_paper = QuestionPaper.objects.get(id=questionpaper_id)
+ paper = AnswerPaper.objects.get(user=request.user, question_paper=q_paper)
answer = request.POST.get('answer')
skip = request.POST.get('skip', None)
-
if skip is not None:
next_q = paper.skip()
- return show_question(request, next_q)
+ return show_question(request, next_q, questionpaper_id)
# Add the answer submitted, regardless of it being correct or not.
new_answer = Answer(question=question, answer=answer, correct=False)
@@ -207,7 +699,7 @@ def check(request, q_id):
# questions, we obtain the results via XML-RPC with the code executed
# safely in a separate process (the code_server.py) running as nobody.
if question.type == 'mcq':
- success = True # Only one attempt allowed for MCQ's.
+ success = True # Only one attempt allowed for MCQ's.
if answer.strip() == question.test.strip():
new_answer.correct = True
new_answer.marks = question.points
@@ -226,16 +718,15 @@ def check(request, q_id):
new_answer.save()
- if not success: # Should only happen for non-mcq questions.
+ if not success: # Should only happen for non-mcq questions.
time_left = paper.time_left()
if time_left == 0:
return complete(request, reason='Your time is up!')
- if not paper.quiz.active:
+ if not paper.question_paper.quiz.active:
return complete(request, reason='The quiz has been deactivated!')
-
context = {'question': question, 'error_message': err_msg,
'paper': paper, 'last_attempt': answer,
- 'quiz_name': paper.quiz.description,
+ 'quiz_name': paper.question_paper.quiz.description,
'time_left': time_left}
ci = RequestContext(request)
@@ -243,60 +734,76 @@ def check(request, q_id):
context_instance=ci)
else:
next_q = paper.completed_question(question.id)
- return show_question(request, next_q)
-
-def quit(request):
- return my_render_to_response('exam/quit.html',
- context_instance=RequestContext(request))
+ return show_question(request, next_q, questionpaper_id)
+
+
+def quit(request, answerpaper_id=None):
+ """Show the quit page when the user logs out."""
+ context = {'id': answerpaper_id}
+ return my_render_to_response('exam/quit.html', context,
+ context_instance=RequestContext(request))
+
+
+def complete(request, reason=None, answerpaper_id=None):
+ """Show a page to inform user that the quiz has been compeleted."""
-def complete(request, reason=None):
user = request.user
+
+ if answerpaper_id is None:
+ logout(request)
+ context = {'message': "You are successfully Logged out."}
+ return my_render_to_response('exam/complete.html', context)
no = False
message = reason or 'The quiz has been completed. Thank you.'
+ if user.groups.filter(name='moderator').count() > 0:
+ message = 'You are successfully Logged out.'
if request.method == 'POST' and 'no' in request.POST:
- no = request.POST.get('no', False)
+ no = True
if not no:
# Logout the user and quit with the message given.
- logout(request)
- context = {'message': message}
- return my_render_to_response('exam/complete.html', context)
+ answer_paper = AnswerPaper.objects.get(id=answerpaper_id)
+ answer_paper.endtime = datetime.datetime.now()
+ answer_paper.save()
+ return my_redirect('/exam/quizzes/')
else:
return my_redirect('/exam/')
def monitor(request, quiz_id=None):
"""Monitor the progress of the papers taken so far."""
+
user = request.user
- if not user.is_authenticated() and not user.is_staff:
+ if not user.is_authenticated() or not is_moderator(user):
raise Http404('You are not allowed to view this page!')
if quiz_id is None:
- quizzes = Quiz.objects.all()
+ q_paper = QuestionPaper.objects.all()
context = {'papers': [],
'quiz': None,
- 'quizzes':quizzes}
+ 'quizzes': q_paper}
return my_render_to_response('exam/monitor.html', context,
context_instance=RequestContext(request))
# quiz_id is not None.
try:
- quiz = Quiz.objects.get(id=quiz_id)
- except Quiz.DoesNotExist:
+ quiz = QuestionPaper.objects.get(id=quiz_id)
+ except QuestionPaper.DoesNotExist:
papers = []
quiz = None
else:
- papers = QuestionPaper.objects.all().annotate(
+ papers = AnswerPaper.objects.all().annotate(
total=Sum('answers__marks')).order_by('-total')
context = {'papers': papers, 'quiz': quiz, 'quizzes': None}
return my_render_to_response('exam/monitor.html', context,
context_instance=RequestContext(request))
+
def get_user_data(username):
"""For a given username, this returns a dictionary of important data
related to the user including all the user's answers submitted.
"""
user = User.objects.get(username=username)
- papers = QuestionPaper.objects.filter(user=user)
+ papers = AnswerPaper.objects.filter(user=user)
data = {}
try:
@@ -309,10 +816,144 @@ def get_user_data(username):
data['papers'] = papers
return data
+
+def show_all_users(request):
+ """Shows all the users who have taken various exams/quiz."""
+
+ user = request.user
+ if not user.is_authenticated() or not is_moderator(user):
+ raise Http404('You are not allowed to view this page !')
+ user = User.objects.filter(username__contains="")
+ questionpaper = AnswerPaper.objects.all()
+ context = {'question': questionpaper}
+ return my_render_to_response('exam/showusers.html', context,
+ context_instance=RequestContext(request))
+
+
+def show_all_quiz(request):
+ """Generates a list of all the quizzes
+ that are currently in the database."""
+
+ user = request.user
+ if not user.is_authenticated() or 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('quiz')
+
+ if data is None:
+ quizzes = Quiz.objects.all()
+ context = {'papers': [],
+ 'quiz': None,
+ 'quizzes': quizzes}
+ return my_render_to_response('exam/show_quiz.html', context,
+ context_instance=RequestContext(request))
+ else:
+ for i in data:
+ quiz = Quiz.objects.get(id=i).delete()
+ quizzes = Quiz.objects.all()
+ context = {'papers': [],
+ 'quiz': None,
+ 'quizzes': quizzes}
+ return my_render_to_response('exam/show_quiz.html', context,
+ context_instance=RequestContext(request))
+
+ elif request.method == 'POST' and request.POST.get('edit') == 'edit':
+ data = request.POST.getlist('quiz')
+ forms = []
+ for j in data:
+ d = Quiz.objects.get(id=j)
+ form = QuizForm()
+ form.initial['start_date'] = d.start_date
+ form.initial['duration'] = d.duration
+ form.initial['active'] = d.active
+ form.initial['description'] = d.description
+ form_tags = d.tags.all()
+ form_tags_split = form_tags.values('name')
+ initial_tags = ""
+ for tag in form_tags_split:
+ initial_tags = initial_tags + str(tag['name']).strip() + ","
+ if (initial_tags == ","):
+ initial_tags = ""
+ form.initial['tags'] = initial_tags
+ forms.append(form)
+ return my_render_to_response('exam/edit_quiz.html',
+ {'forms': forms, 'data': data},
+ context_instance=RequestContext(request))
+ else:
+ quizzes = Quiz.objects.all()
+ context = {'papers': [],
+ 'quiz': None,
+ 'quizzes': quizzes}
+ return my_render_to_response('exam/show_quiz.html', context,
+ context_instance=RequestContext(request))
+
+
+def show_all_questions(request):
+ """Show a list of all the questions currently in the databse."""
+
+ user = request.user
+ if not user.is_authenticated() or 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 None:
+ questions = Question.objects.all()
+ context = {'papers': [],
+ 'question': None,
+ 'questions': questions}
+ return my_render_to_response('exam/showquestions.html', context,
+ context_instance=RequestContext(request))
+ else:
+ for i in data:
+ question = Question.objects.get(id=i).delete()
+ questions = Question.objects.all()
+ context = {'papers': [],
+ 'question': None,
+ 'questions': questions}
+ return my_render_to_response('exam/showquestions.html', context,
+ context_instance=RequestContext(request))
+ elif request.method == 'POST' and request.POST.get('edit') == 'edit':
+ data = request.POST.getlist('question')
+
+ forms = []
+ for j in data:
+ d = Question.objects.get(id=j)
+ form = QuestionForm()
+ form.initial['summary'] = d.summary
+ form.initial['description'] = d.description
+ form.initial['points'] = d.points
+ form.initial['test'] = d.test
+ form.initial['options'] = d.options
+ form.initial['type'] = d.type
+ form.initial['active'] = d.active
+ form_tags = d.tags.all()
+ form_tags_split = form_tags.values('name')
+ initial_tags = ""
+ for tag in form_tags_split:
+ initial_tags = initial_tags + str(tag['name']).strip() + ","
+ if (initial_tags == ","):
+ initial_tags = ""
+ form.initial['tags'] = initial_tags
+ forms.append(form)
+ return my_render_to_response('exam/edit_question.html',
+ {'forms': forms, 'data': data},
+ context_instance=RequestContext(request))
+ else:
+ questions = Question.objects.all()
+ context = {'papers': [],
+ 'question': None,
+ 'questions': questions}
+ return my_render_to_response('exam/showquestions.html', context,
+ context_instance=RequestContext(request))
+
+
def user_data(request, username):
"""Render user data."""
+
current_user = request.user
- if not current_user.is_authenticated() and not current_user.is_staff:
+ if not current_user.is_authenticated() or not is_moderator(user):
raise Http404('You are not allowed to view this page!')
data = get_user_data(username)
@@ -321,12 +962,13 @@ def user_data(request, username):
return my_render_to_response('exam/user_data.html', context,
context_instance=RequestContext(request))
+
def grade_user(request, username):
"""Present an interface with which we can easily grade a user's papers
and update all their marks and also give comments for each paper.
"""
current_user = request.user
- if not current_user.is_authenticated() and not current_user.is_staff:
+ if not current_user.is_authenticated() or not is_moderator(current_user):
raise Http404('You are not allowed to view this page!')
data = get_user_data(username)
@@ -334,11 +976,12 @@ def grade_user(request, username):
papers = data['papers']
for paper in papers:
for question, answers in paper.get_question_answers().iteritems():
- marks = float(request.POST.get('q%d_marks'%question.id))
+ marks = float(request.POST.get('q%d_marks' % question.id))
last_ans = answers[-1]
last_ans.marks = marks
last_ans.save()
- paper.comments = request.POST.get('comments_%d'%paper.quiz.id)
+ paper.comments = request.POST.get(\
+ 'comments_%d' % paper.question_paper.id)
paper.save()
context = {'data': data}
@@ -348,4 +991,3 @@ def grade_user(request, username):
context = {'data': data}
return my_render_to_response('exam/grade_user.html', context,
context_instance=RequestContext(request))
-