From 2a0e009c856b0ad8a28b613fcfde8f6cd92dca02 Mon Sep 17 00:00:00 2001 From: Primal Pappachan Date: Tue, 27 Mar 2012 14:56:23 +0530 Subject: Added buildout files --- README.rst | 4 - __init__.py | 0 allotter/__init__.py | 2 - allotter/admin.py | 7 - allotter/forms.py | 110 --------- allotter/management/__init__.py | 0 allotter/management/commands/__init__.py | 0 allotter/management/commands/loadexam.py | 40 ---- allotter/management/commands/loadoptions.py | 60 ----- allotter/management/commands/loadusers.py | 65 ------ allotter/models.py | 136 ----------- allotter/templatetags/__init__.py | 0 allotter/templatetags/range_filter.py | 27 --- allotter/tests.py | 16 -- allotter/urls.py | 11 - allotter/views.py | 260 --------------------- bootstrap.py | 77 ++++++ buildout.cfg | 26 +++ choice_seeker/README.rst | 4 + choice_seeker/__init__.py | 0 choice_seeker/allotter/__init__.py | 2 + choice_seeker/allotter/admin.py | 7 + choice_seeker/allotter/forms.py | 110 +++++++++ choice_seeker/allotter/management/__init__.py | 0 .../allotter/management/commands/__init__.py | 0 .../allotter/management/commands/loadexam.py | 40 ++++ .../allotter/management/commands/loadoptions.py | 60 +++++ .../allotter/management/commands/loadusers.py | 65 ++++++ choice_seeker/allotter/models.py | 136 +++++++++++ choice_seeker/allotter/templatetags/__init__.py | 0 .../allotter/templatetags/range_filter.py | 27 +++ choice_seeker/allotter/tests.py | 16 ++ choice_seeker/allotter/urls.py | 11 + choice_seeker/allotter/views.py | 260 +++++++++++++++++++++ choice_seeker/manage.py | 14 ++ choice_seeker/settings.py | 182 +++++++++++++++ choice_seeker/template/allotter/apply.html | 109 +++++++++ choice_seeker/template/allotter/complete.html | 60 +++++ choice_seeker/template/allotter/details.html | 19 ++ choice_seeker/template/allotter/hello.html | 11 + choice_seeker/template/allotter/login.html | 21 ++ choice_seeker/template/allotter/register.html | 17 ++ choice_seeker/template/base.html | 23 ++ choice_seeker/urls.py | 18 ++ manage.py | 14 -- settings.py | 182 --------------- template/allotter/apply.html | 109 --------- template/allotter/complete.html | 60 ----- template/allotter/details.html | 19 -- template/allotter/hello.html | 11 - template/allotter/login.html | 21 -- template/allotter/register.html | 17 -- template/base.html | 23 -- urls.py | 18 -- 54 files changed, 1315 insertions(+), 1212 deletions(-) delete mode 100644 README.rst delete mode 100644 __init__.py delete mode 100644 allotter/__init__.py delete mode 100644 allotter/admin.py delete mode 100644 allotter/forms.py delete mode 100644 allotter/management/__init__.py delete mode 100644 allotter/management/commands/__init__.py delete mode 100644 allotter/management/commands/loadexam.py delete mode 100644 allotter/management/commands/loadoptions.py delete mode 100644 allotter/management/commands/loadusers.py delete mode 100644 allotter/models.py delete mode 100644 allotter/templatetags/__init__.py delete mode 100644 allotter/templatetags/range_filter.py delete mode 100644 allotter/tests.py delete mode 100644 allotter/urls.py delete mode 100644 allotter/views.py create mode 100644 bootstrap.py create mode 100644 buildout.cfg create mode 100644 choice_seeker/README.rst create mode 100644 choice_seeker/__init__.py create mode 100644 choice_seeker/allotter/__init__.py create mode 100644 choice_seeker/allotter/admin.py create mode 100644 choice_seeker/allotter/forms.py create mode 100644 choice_seeker/allotter/management/__init__.py create mode 100644 choice_seeker/allotter/management/commands/__init__.py create mode 100644 choice_seeker/allotter/management/commands/loadexam.py create mode 100644 choice_seeker/allotter/management/commands/loadoptions.py create mode 100644 choice_seeker/allotter/management/commands/loadusers.py create mode 100644 choice_seeker/allotter/models.py create mode 100644 choice_seeker/allotter/templatetags/__init__.py create mode 100644 choice_seeker/allotter/templatetags/range_filter.py create mode 100644 choice_seeker/allotter/tests.py create mode 100644 choice_seeker/allotter/urls.py create mode 100644 choice_seeker/allotter/views.py create mode 100755 choice_seeker/manage.py create mode 100644 choice_seeker/settings.py create mode 100644 choice_seeker/template/allotter/apply.html create mode 100644 choice_seeker/template/allotter/complete.html create mode 100644 choice_seeker/template/allotter/details.html create mode 100644 choice_seeker/template/allotter/hello.html create mode 100644 choice_seeker/template/allotter/login.html create mode 100644 choice_seeker/template/allotter/register.html create mode 100644 choice_seeker/template/base.html create mode 100644 choice_seeker/urls.py delete mode 100755 manage.py delete mode 100644 settings.py delete mode 100644 template/allotter/apply.html delete mode 100644 template/allotter/complete.html delete mode 100644 template/allotter/details.html delete mode 100644 template/allotter/hello.html delete mode 100644 template/allotter/login.html delete mode 100644 template/allotter/register.html delete mode 100644 template/base.html delete mode 100644 urls.py diff --git a/README.rst b/README.rst deleted file mode 100644 index af82358..0000000 --- a/README.rst +++ /dev/null @@ -1,4 +0,0 @@ - -**Just got started** - -http://wiki.fossee.in/JAM diff --git a/__init__.py b/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/allotter/__init__.py b/allotter/__init__.py deleted file mode 100644 index b48e5a0..0000000 --- a/allotter/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -import os - diff --git a/allotter/admin.py b/allotter/admin.py deleted file mode 100644 index 0c14e78..0000000 --- a/allotter/admin.py +++ /dev/null @@ -1,7 +0,0 @@ -from allotter.models import Exam, Option, Application, Profile -from django.contrib import admin - -admin.site.register(Exam) -admin.site.register(Option) -admin.site.register(Application) -admin.site.register(Profile) diff --git a/allotter/forms.py b/allotter/forms.py deleted file mode 100644 index 65e4cf6..0000000 --- a/allotter/forms.py +++ /dev/null @@ -1,110 +0,0 @@ - -from django import forms -from allotter.models import Profile -from django.forms.extras.widgets import SelectDateWidget - -from django.utils.encoding import * - -from django.contrib.auth import authenticate -from django.contrib.auth.models import User - -from string import digits - -BIRTH_YEAR_CHOICES = ('1986','1987','1988','1989','1990','1991') - - -class UserLoginForm(forms.Form): - - ##Registration Number as Username - username = forms.IntegerField(label="Registration Number", - help_text="As on your Examination ID Card") - - ##Application number as password - password = forms.CharField(label = "Application Number", - max_length=10, help_text="As on your Examination ID Card") - - dob = forms.DateField(label="Date of Birth", - widget=SelectDateWidget(years=BIRTH_YEAR_CHOICES), - initial=datetime.date.today) - - def clean_username(self): - u_name = self.cleaned_data["username"] - - if not u_name: - raise forms.ValidationError("Enter an username.") - - ##Verifies whether username contains only digits and is not - ##longer than 7, i.e Username == Registration Number. - if str(u_name).strip(digits) or len(str(u_name)) != 7: - msg = "Invalid Registration Number" - raise forms.ValidationError(msg) - - ##Verifying whether the user already exists in the database - ##Raising error otherwise - try: - User.objects.get(username__exact = u_name) - return u_name - except User.DoesNotExist: - raise forms.ValidationError("Entered Registration Number haven't appeared for JAM Exam.") - - def clean_password(self): - - pwd = self.cleaned_data['password'] - - ##Verifying the length of application number and whether it contains - ##only digits. - - if str(pwd).strip(digits) and len(pwd) != 5: - msg = "Not a valid Application Number" - raise forms.ValidationError(msg) - - return pwd - - def clean(self): - super(UserLoginForm, self).clean() - u_name, pwd = self.cleaned_data.get('username'), self.cleaned_data.get('password') - dob = self.cleaned_data['dob'] - try: - current_user = User.objects.get(username__exact = u_name) - profile = current_user.get_profile() - if profile.dob != dob: - raise forms.ValidationError("Date of Birth doesn't match.") - except User.DoesNotExist: - raise forms.ValidationError("Correct the following errors and try logging in again.") - - - ##Authentication part - user = authenticate(username = u_name, password = pwd) - if not user: - raise forms.ValidationError("Application Number or Registration Number doesn't match.") - return user - - -class UserDetailsForm(forms.Form): - - def __init__(self, user, *args, **kwargs): - self.user = user - super(UserDetailsForm, self).__init__(*args, **kwargs) - - email = forms.EmailField(label="Email Address", - help_text="Enter a valid email id if you have any.") - phone_number = forms.IntegerField(label="Phone number", - help_text="10 digit number with code") - - - def clean_phone_number(self): - pno = self.cleaned_data['phone_number'] - if str(pno).strip(digits) or len(str(pno)) != 10: - raise forms.ValidationError("Not a valid phone number") - return pno - - def save(self): - cleaned_data = self.cleaned_data - user_profile = self.user.get_profile() - - user_profile.secondary_email = self.cleaned_data['email'] - user_profile.phone_number = self.cleaned_data['phone_number'] - - user_profile.save() - - diff --git a/allotter/management/__init__.py b/allotter/management/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/allotter/management/commands/__init__.py b/allotter/management/commands/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/allotter/management/commands/loadexam.py b/allotter/management/commands/loadexam.py deleted file mode 100644 index 2fedb66..0000000 --- a/allotter/management/commands/loadexam.py +++ /dev/null @@ -1,40 +0,0 @@ -from csv import reader -from django.core.management.base import BaseCommand, CommandError -from allotter.models import Exam - -class Command(BaseCommand): - args = '' - help = "Give the filename of the csv file that has all the exam code and exam name relation" - - def handle(self, *args, **options): - - clean_exam() - - for fname in args: - load_exam(fname) - - self.stdout.write('Done\n') - - -def clean_exam(): - """Removes all the objects from the database, required as if not done there might be a case of multile entries""" - data = Exam.objects.all() - data.delete() - -def load_exam(filename): - """Load exam code and exam name from the given csv file. The file should - declare a list of "exam_code;exam_name". - """ - try: - csvFile = open(filename, 'rb') - except IOError as (errno,strerror): - print "I/O error({0}): {1}".format(errno, strerror) - - csvReader = reader(csvFile, delimiter=";") - - for data in csvReader: - new_exam = Exam.objects.create() - new_exam.exam_code = data[0] - new_exam.exam_name = data[1] - new_exam.save() - print "Added ({0} : {1})".format(data[0], data[1]) \ No newline at end of file diff --git a/allotter/management/commands/loadoptions.py b/allotter/management/commands/loadoptions.py deleted file mode 100644 index f7c01e6..0000000 --- a/allotter/management/commands/loadoptions.py +++ /dev/null @@ -1,60 +0,0 @@ -from optparse import make_option -from csv import reader -from django.core.management.base import BaseCommand -from allotter.models import Exam, Option - -class Command(BaseCommand): - option_list = BaseCommand.option_list + ( - make_option('--pcc',metavar='Paper course code file name', type=str), - make_option('--cc',metavar='Course code file name', type=str), - ) - help = "Give the filenames of the csv files that has all the option code, name and exam code relation" - - def handle(self, *args, **options): - - clean_option() - - load_option(options) - - self.stdout.write('Done\n') - - -def clean_option(): - """Removes all the objects from the database, required as if not done there might be a case of multiple entries""" - data = Option.objects.all() - data.delete() - -def load_option(options): - """Load option code and option name from the given csv file. The file should - declare a list of "exam_code,option_code,option,code". - """ - paperCourseFileName=options.get('pcc') - courseCodeFileName=options.get('cc') - try: - paperCourseFile = open(paperCourseFileName, 'rb') - except IOError as (errno,strerror): - print "I/O error({0}): {1}".format(errno, strerror) - - try: - courseCodeFile = open(courseCodeFileName, 'rb') - except IOError as (errno,strerror): - print "I/O error({0}): {1}".format(errno, strerror) - - paperReader = reader(paperCourseFile, delimiter=",") - courseReader = reader(courseCodeFile, delimiter=",") - - courseDict = {} - - for data in courseReader: - courseDict[int(data[0])]=data[1] - - for data in paperReader: - exam = Exam.objects.get(exam_code=data[0]) - for value in data[1:len(data)]: - try: - new_option = Option.objects.get(opt_code=value) - except Option.DoesNotExist: - new_option = Option(opt_name=courseDict[int(value)],opt_code=value) - new_option.save() - new_option.exam.add(exam) - print "Added (option {0} with code {1} and exam {2})".format(courseDict[int(value)],value,exam) \ No newline at end of file diff --git a/allotter/management/commands/loadusers.py b/allotter/management/commands/loadusers.py deleted file mode 100644 index 99fd075..0000000 --- a/allotter/management/commands/loadusers.py +++ /dev/null @@ -1,65 +0,0 @@ -from optparse import make_option -from datetime import datetime -from csv import DictReader -from django.core.management.base import BaseCommand -from allotter.models import Exam, Application, User, Profile - -class Command(BaseCommand): - option_list = BaseCommand.option_list + ( - make_option('--usdf',metavar='User details file name', type=str), - ) - help = "Give the filename of the csv files that has all the details of the users" - - def handle(self, *args, **options): - - clean_users() - - load_users(options) - - self.stdout.write('Done\n') - - -def clean_users(): - """Removes all the objects from the database, required as if not done there might be a case of multiple entries""" - User.objects.filter(is_superuser=False).delete() - -def load_users(options): - """Load option code and option name from the given csv file. The file should - declare a list of "exam_code,option_code,option,code". - """ - userDetailsFileName=options.get('usdf') - try: - userDetailsFile = open(userDetailsFileName, 'rb') - except IOError as (errno,strerror): - print "I/O error({0}): {1}".format(errno, strerror) - - - userReader = DictReader(userDetailsFile, delimiter=":") - - - for data in userReader: - appno = data['AppNo.'] - regno = data['Reg.No.'] - new_user = User.objects.create_user(regno, password=appno, email="") - application = Application(user=new_user) - application.np = int(data['NP']) - if data['P1'].strip(): - application.first_paper = Exam.objects.get(exam_code=data['P1']) - try: - application.second_paper = Exam.objects.get(exam_code=data['P2']) - except: - pass - else: - application.first_paper = Exam.objects.get(exam_code=data['P2']) - - - application.nat = data['Nat'] - application.gender = data['Gdr'] - application.cent = data['Cent'] - application.cgy = data['Cgy'] - application.save() - dob = datetime.strptime(data['DOB'], "%d/%m/%y") - new_profile = Profile(user=new_user, application=application) - new_profile.dob = dob - new_profile.save() - print "Added user with {0} and {1} with dob as {2}".format(appno,regno,dob) \ No newline at end of file diff --git a/allotter/models.py b/allotter/models.py deleted file mode 100644 index 9da8213..0000000 --- a/allotter/models.py +++ /dev/null @@ -1,136 +0,0 @@ -from django.db import models -from django.contrib.auth.models import User - -##EXAMINATION_SUBJECTS = ( -## ("Physics", "Physics"), -## ("Mathematics", "Mathematics"), -## ("Chemistry", "Chemistry"), -## ) - -##CATEGORIES = ( -## ("GEN", "GEN"), -## ("OBC", "OBC(Non-Creamy Layer)"), -## ("SC", "SC"), -## ("ST", "ST"), -## ) - -##AVAILABLE_OPTIONS = ( -## ("MScChem", "M.Sc Chemisty"), -## ("M.Sc-Physics-IIT-Bombay", "M.Sc Physics IIT Bombay"), -## ("MScMath","M.Sc Mathematics"), -## ("MscHist", "M.Sc History"), -## ("MSc-PhD Dual-Degree-IIT-Bombay", "MSc-PhD Dual Degree IIT Bombay"), -## ("M.Sc Physics-IIT-Madras", "M.Sc Physics IIT Madras"), -## ("M.Sc-Physics-IIT-Guwahati", "M.Sc Physics IIT Guwahati"), -## ("M.Sc-Physics-IIT-KGP", "M.Sc Physics IIT KGP"), -## ("M.Sc-Physics-IIT-Roorkee", "M.Sc Physics IIT Roorkee"), -##) - -##GENDER_CHOICES = ( -## ("M", "Male"), -## ("F", "Female"),) - -##APPLICATION_STATUS = ( -## ("I", "Incomplete"), -## ("Submitted", "Submitted")) - -##BIRTH_YEAR_CHOICES = ('1989', '1990', '1991') - -class Exam(models.Model): - """ - Table for Examination Codes and Subject names. - """ - ##PH for Physics, CY for Chemistry - exam_code = models.CharField(max_length=100, - verbose_name=u"Test Paper code", - help_text=u"Unique code for the Test") - - exam_name = models.CharField(max_length=100, - verbose_name=u"Test Paper", - help_text=u"Subject name of the Test") - - def __unicode__(self): - return self.exam_name - - -class Option(models.Model): - """ - Options Table, Foreign Keyed with Examination. - """ - - opt_name = models.CharField(max_length=100, - verbose_name=u"Programme name", - help_text=u"Programme Title") - - opt_code = models.IntegerField(max_length=3, - verbose_name=u"Programme Code") - - opt_location = models.CharField(max_length=30, - verbose_name=u"Programme Location", - help_text=u"Offered by which IIT") - - exam = models.ManyToManyField(Exam) - - class Meta: - verbose_name_plural = "Options" - - def __unicode__(self): - return unicode(self.opt_code) - - -class Application(models.Model): - """An application for the student - one per student - """ - user = models.OneToOneField(User) - - ##To be filled by applicant - options_selected = models.CharField(max_length=5000,help_text="CSV formatted list of options", blank=True) - - ##Prefilled fields - np = models.IntegerField(max_length=2, help_text="Number of Test Papers") - - ##Mandatory First Subject - first_paper = models.ForeignKey(Exam, related_name="first_paper") - - ##Second subject can be left blank or null - second_paper = models.ForeignKey(Exam, related_name="second_paper", blank=True, null=True) - - nat = models.CharField(max_length=10, verbose_name="Nationality") - - gender = models.CharField(max_length=2, verbose_name="Gender") - - cent = models.IntegerField(max_length=10, verbose_name="Center Code") - - cgy = models.CharField(max_length=10, verbose_name="Category") - - pd = models.BooleanField(verbose_name="Physical Disability", default=False, blank=True) - - submitted = models.BooleanField(verbose_name="Submission Status", default=False) - - def __unicode__(self): - u = self.user - return u'Application for {0}'.format(u.username) - -class Profile(models.Model): - - user = models.OneToOneField(User) - - #Used for verification purposes - dob = models.DateField(verbose_name=u"Date of Birth", - help_text=u"Date of birth as given in the application") - - secondary_email = models.EmailField(verbose_name=u"Secondary Email", - help_text=u"Email address read from user after authentication") - - phone_number = models.IntegerField(max_length=10, verbose_name="Phone Number", - help_text=u"Phone number read from user after authentication") - - #Application for the Profile - application = models.ForeignKey(Application) - - def __unicode__(self): - u = self.user - return u'User Profile {0}'.format(u.username) - - - diff --git a/allotter/templatetags/__init__.py b/allotter/templatetags/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/allotter/templatetags/range_filter.py b/allotter/templatetags/range_filter.py deleted file mode 100644 index 1ce43d8..0000000 --- a/allotter/templatetags/range_filter.py +++ /dev/null @@ -1,27 +0,0 @@ -##Credits : http://djangosnippets.org/snippets/1357/ - -from django.template import Library - -register = Library() - -@register.filter -def get_range( value ): - """ - Filter - returns a list containing range made from given value - Usage (in template): - - - - Results with the HTML: - - - Instead of 3 one may use the variable set in the views - """ - return range( value ) - diff --git a/allotter/tests.py b/allotter/tests.py deleted file mode 100644 index 501deb7..0000000 --- a/allotter/tests.py +++ /dev/null @@ -1,16 +0,0 @@ -""" -This file demonstrates writing tests using the unittest module. These will pass -when you run "manage.py test". - -Replace this with more appropriate tests for your application. -""" - -from django.test import TestCase - - -class SimpleTest(TestCase): - def test_basic_addition(self): - """ - Tests that 1 + 1 always equals 2. - """ - self.assertEqual(1 + 1, 2) diff --git a/allotter/urls.py b/allotter/urls.py deleted file mode 100644 index 6556c62..0000000 --- a/allotter/urls.py +++ /dev/null @@ -1,11 +0,0 @@ -from django.conf.urls.defaults import patterns, url - -urlpatterns = patterns('allotter.views', - url(r'^login/$', 'user_login'), - url(r'^logout/$', 'user_logout'), - url(r'^(?P\d+)/apply/$', 'apply'), - url(r'^(?P\d+)/details/$', 'submit_details'), - url(r'^(?P\d+)/get_pdf/$', 'generate_pdf'), - url(r'^(?P\d+)/submit/$', 'submit_options', name='submit_options'), - url(r'^(?P\d+)/complete/$', 'complete_allotment', name='complete_allotment'), -) diff --git a/allotter/views.py b/allotter/views.py deleted file mode 100644 index fb819fc..0000000 --- a/allotter/views.py +++ /dev/null @@ -1,260 +0,0 @@ -from django.contrib.auth import login, logout, authenticate -from django.contrib.auth.decorators import login_required -from django.shortcuts import render, redirect, get_object_or_404 - -from django.http import Http404 -from django.http import HttpResponse -from django.http import HttpResponseRedirect - -from django.core.urlresolvers import reverse - -from django.contrib.auth.models import User -from allotter.models import Profile, Option, Exam -from allotter.forms import UserLoginForm, UserDetailsForm - -from itertools import chain - -#Reportlab libraries -from reportlab.platypus import Table, TableStyle, SimpleDocTemplate, Paragraph, Spacer -from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle -from reportlab.lib import colors -from reportlab.lib.units import inch -from reportlab.lib.enums import TA_JUSTIFY - -import time - -def user_login(request): - """ - Verify the user credentials and log the user in. - """ - - user = request.user - if user.is_authenticated(): - status = user.get_profile().application.submitted #Getting the submission status - if status: #If already submitted, takes to Completion Page - return HttpResponseRedirect(reverse('allotter.views.complete_allotment', args=(user.username,))) - else: #Otherwise to Option Choosing Page - return HttpResponseRedirect(reverse('allotter.views.apply', args=(user.username,))) - - if request.method == "POST": - form = UserLoginForm(request.POST) - if form.is_valid(): - user = form.cleaned_data - login(request, user) - status = user.get_profile().application.submitted #Getting the submission status - if status: - return HttpResponseRedirect(reverse('allotter.views.complete_allotment', args=(user.username,))) - else: - return HttpResponseRedirect(reverse('allotter.views.submit_details', args=(user.username,))) - else: - context = {"form": form} - return render(request, 'allotter/login.html', context) - else: - form = UserLoginForm() - context = {"form": form} - return render(request, 'allotter/login.html', context) - - -@login_required -def submit_details(request, reg_no): - """ - Get the secondary email address, phone number and save it to the Profile. - """ - user = request.user - - if request.method == "POST": - form = UserDetailsForm(user, request.POST) - if form.is_valid(): - data = form.cleaned_data - form.save() - return redirect("/allotter/apply/") - else: - return render(request, 'allotter/details.html', {'form':form}) - - else: - form = UserDetailsForm(request.user) - context = {"form": form} - return render(request, 'allotter/details.html', context) - -def get_details(user, error_message = ""): - """ - Retrieves the information about Test paper(s) and options available - and returns them in a dictionary(context) for passing to the Template. - """ - user_profile = user.get_profile() - user_application = user_profile.application - np = user_application.np #Number of Papers - first_paper = user_application.first_paper #First Paper Name - options_available_first = Option.objects.filter(exam__exam_name=first_paper).distinct() #Options for First paper - oafl = len(options_available_first) - if np == 2: #If written two exams - second_paper = user_application.second_paper - options_available_second = Option.objects.filter(exam__exam_name=second_paper).distinct() - oasl = len(options_available_second) - context = {'user': user, 'first_paper': first_paper, - 'options_available_first' : options_available_first, - 'second_paper': second_paper, - 'options_available_second' : options_available_second, - 'np' : np, 'options_range': range(1, oafl + oasl + 1, 1), - 'error_message': error_message} - else: #If written only one exam - context = {'user': user, 'first_paper': first_paper, - 'options_available_first' : options_available_first, - 'options_range': range(1, oafl + 1, 1), - 'np' : np, 'error_message' : error_message} - return context - -@login_required -def apply(request, reg_no): - """ - Displays the application page for an authenticated user. - """ - user = request.user - if not(user.is_authenticated()): - return redirect('/allotter/login/') - - context = get_details(user) - - return render(request, 'allotter/apply.html', context) - - -def user_logout(request): - ##Logouts the user. - logout(request) - return redirect ('/allotter/login/') - -#TODO: Extensive Testing - -@login_required -def submit_options(request, reg_no): - """ - Gets the Options and their preference number through the POST object and - stores them as list(sorted according to preferences). Options with None are - ignored. - """ - user = get_object_or_404(User, username=reg_no) - user_profile = user.get_profile() - user_application = user_profile.application - np = user_application.np - first_paper = user_application.first_paper #First Paper Name - options_available_first = Option.objects.filter(exam__exam_name=first_paper).distinct() #Options for First paper - - if np == 2: #If qualified for second paper - second_paper = user_application.second_paper #Second Paper Name - options_available_second = Option.objects.filter(exam__exam_name=second_paper).distinct() #Options for second paper - options_available_list = chain(options_available_first, options_available_second) #chaining the two lists - else: - options_available_list = options_available_first - - options_chosen_list = [] #Initializing empty list for storing options - for option in options_available_list: - option_pref = request.POST[unicode(option.opt_code)] - options_chosen_list.append([option_pref, str(option.opt_code)]) #[preference, option code] - - options_chosen_list.sort() #Sorting by preference - options_code_list = [] - for opt in options_chosen_list: - if int(opt[0]): #ignoring the options for which None was marked - options_code_list.append(opt[1]) - - user_application.options_selected = options_code_list #Saving the data in model - user_application.submitted = True #Submission Status - user_application.save() - return HttpResponseRedirect(reverse('allotter.views.complete_allotment', args=(reg_no,))) - -def complete_allotment(request, reg_no): - """ - Passes the chosen options queryset to the Completion Page Template - """ - user = get_object_or_404(User, username=reg_no) - sec_email = user.get_profile().secondary_email - options_chosen = get_chosen_options(user) - context = {'username': reg_no, 'email': sec_email, - 'options_chosen': options_chosen} - - return render(request, 'allotter/complete.html', context) - - -def get_chosen_options(user): - """ - Reads the options submitted by the user in the Application page - """ - user_profile = user.get_profile() - user_application = user_profile.application - np = user_application.np - ocl = eval(user_application.options_selected) - chosen_options = [] - for oc in ocl: - chosen_options.append(Option.objects.get(opt_code=int(oc))) - return chosen_options - - -@login_required -def generate_pdf(request, reg_no): - """ - The Ugly code for generating the pdf using ReportLab. - """ - - user = get_object_or_404(User, username=reg_no) - user_profile = user.get_profile() - user_application = user_profile.application - np = user_application.np - - response = HttpResponse(mimetype='application/pdf') - response['Content-Disposition'] = 'attachment; filename=JAM2012_Allottment.pdf' - - elements = [] - doc = SimpleDocTemplate(response) - - formatted_time = time.ctime() - styles = getSampleStyleSheet() - styles.add(ParagraphStyle(name='Justify', alignment=TA_JUSTIFY)) - - ptext = 'JAM 2012 Allotment.' - elements.append(Paragraph(ptext, styles["Justify"])) - elements.append(Spacer(4, 20)) - - ptext = 'Registration Number: %s' % reg_no - elements.append(Paragraph(ptext, styles["Normal"])) - elements.append(Spacer(1, 12)) - - ptext = 'Number of Papers Eligible: %s' % np - elements.append(Paragraph(ptext, styles["Normal"])) - elements.append(Spacer(1, 12)) - - ptext = 'No options were chosen.' - elements.append(Paragraph(ptext, styles["Normal"])) - elements.append(Spacer(1, 12)) - - data = [] - options = get_chosen_options(user) ##Put a check to show when the options chosen is empty - - if not(options): - doc.build(elements) - return response - - ptext = 'Following are the options in order of preference' - elements.append(Paragraph(ptext, styles["Normal"])) - elements.append(Spacer(1, 12)) - - counter = 1 - for opt in options: - data.append([counter, opt.opt_code, opt.opt_location, opt.opt_name]) - counter = counter + 1 - - t = Table(data) - t.setStyle(TableStyle([('GRID',(0,0),(3,len(options)),1,colors.black), - ('TEXTCOLOR',(0,0),(0,-1),colors.green)])) - - elements.append(t) - - ptext = '%s' % formatted_time - elements.append(Paragraph(ptext, styles["Normal"])) - elements.append(Spacer(1, 12)) - - doc.build(elements) - - return response - - - diff --git a/bootstrap.py b/bootstrap.py new file mode 100644 index 0000000..7728587 --- /dev/null +++ b/bootstrap.py @@ -0,0 +1,77 @@ +############################################################################## +# +# Copyright (c) 2006 Zope Corporation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# +############################################################################## +"""Bootstrap a buildout-based project + +Simply run this script in a directory containing a buildout.cfg. +The script accepts buildout command-line options, so you can +use the -c option to specify an alternate configuration file. + +$Id$ +""" + +import os, shutil, sys, tempfile, urllib2 + +tmpeggs = tempfile.mkdtemp() + +is_jython = sys.platform.startswith('java') + +try: + import pkg_resources +except ImportError: + ez = {} + exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py' + ).read() in ez + ez['use_setuptools'](to_dir=tmpeggs, download_delay=0) + + import pkg_resources + +if sys.platform == 'win32': + def quote(c): + if ' ' in c: + return '"%s"' % c # work around spawn lamosity on windows + else: + return c +else: + def quote (c): + return c + +cmd = 'from setuptools.command.easy_install import main; main()' +ws = pkg_resources.working_set + +if is_jython: + import subprocess + + assert subprocess.Popen([sys.executable] + ['-c', quote(cmd), '-mqNxd', + quote(tmpeggs), 'zc.buildout'], + env=dict(os.environ, + PYTHONPATH= + ws.find(pkg_resources.Requirement.parse('setuptools')).location + ), + ).wait() == 0 + +else: + assert os.spawnle( + os.P_WAIT, sys.executable, quote (sys.executable), + '-c', quote (cmd), '-mqNxd', quote (tmpeggs), 'zc.buildout', + dict(os.environ, + PYTHONPATH= + ws.find(pkg_resources.Requirement.parse('setuptools')).location + ), + ) == 0 + +ws.add_entry(tmpeggs) +ws.require('zc.buildout') +import zc.buildout.buildout +zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap']) +shutil.rmtree(tmpeggs) diff --git a/buildout.cfg b/buildout.cfg new file mode 100644 index 0000000..517472e --- /dev/null +++ b/buildout.cfg @@ -0,0 +1,26 @@ +[buildout] +parts = + django + django-command-extensions +eggs = + South +versions = versions + +[versions] +django = 1.3 + +[django] +recipe = djangorecipe +project = aloha +settings = settings +wsgi = true +wsgilog=wsgi.log +eggs = + ${buildout:eggs} +extra-paths = + ${django-command-extensions:location} + aloha + +[django-command-extensions] +recipe = zerokspot.recipe.git +repository = http://github.com/django-extensions/django-extensions.git diff --git a/choice_seeker/README.rst b/choice_seeker/README.rst new file mode 100644 index 0000000..af82358 --- /dev/null +++ b/choice_seeker/README.rst @@ -0,0 +1,4 @@ + +**Just got started** + +http://wiki.fossee.in/JAM diff --git a/choice_seeker/__init__.py b/choice_seeker/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/choice_seeker/allotter/__init__.py b/choice_seeker/allotter/__init__.py new file mode 100644 index 0000000..b48e5a0 --- /dev/null +++ b/choice_seeker/allotter/__init__.py @@ -0,0 +1,2 @@ +import os + diff --git a/choice_seeker/allotter/admin.py b/choice_seeker/allotter/admin.py new file mode 100644 index 0000000..0c14e78 --- /dev/null +++ b/choice_seeker/allotter/admin.py @@ -0,0 +1,7 @@ +from allotter.models import Exam, Option, Application, Profile +from django.contrib import admin + +admin.site.register(Exam) +admin.site.register(Option) +admin.site.register(Application) +admin.site.register(Profile) diff --git a/choice_seeker/allotter/forms.py b/choice_seeker/allotter/forms.py new file mode 100644 index 0000000..65e4cf6 --- /dev/null +++ b/choice_seeker/allotter/forms.py @@ -0,0 +1,110 @@ + +from django import forms +from allotter.models import Profile +from django.forms.extras.widgets import SelectDateWidget + +from django.utils.encoding import * + +from django.contrib.auth import authenticate +from django.contrib.auth.models import User + +from string import digits + +BIRTH_YEAR_CHOICES = ('1986','1987','1988','1989','1990','1991') + + +class UserLoginForm(forms.Form): + + ##Registration Number as Username + username = forms.IntegerField(label="Registration Number", + help_text="As on your Examination ID Card") + + ##Application number as password + password = forms.CharField(label = "Application Number", + max_length=10, help_text="As on your Examination ID Card") + + dob = forms.DateField(label="Date of Birth", + widget=SelectDateWidget(years=BIRTH_YEAR_CHOICES), + initial=datetime.date.today) + + def clean_username(self): + u_name = self.cleaned_data["username"] + + if not u_name: + raise forms.ValidationError("Enter an username.") + + ##Verifies whether username contains only digits and is not + ##longer than 7, i.e Username == Registration Number. + if str(u_name).strip(digits) or len(str(u_name)) != 7: + msg = "Invalid Registration Number" + raise forms.ValidationError(msg) + + ##Verifying whether the user already exists in the database + ##Raising error otherwise + try: + User.objects.get(username__exact = u_name) + return u_name + except User.DoesNotExist: + raise forms.ValidationError("Entered Registration Number haven't appeared for JAM Exam.") + + def clean_password(self): + + pwd = self.cleaned_data['password'] + + ##Verifying the length of application number and whether it contains + ##only digits. + + if str(pwd).strip(digits) and len(pwd) != 5: + msg = "Not a valid Application Number" + raise forms.ValidationError(msg) + + return pwd + + def clean(self): + super(UserLoginForm, self).clean() + u_name, pwd = self.cleaned_data.get('username'), self.cleaned_data.get('password') + dob = self.cleaned_data['dob'] + try: + current_user = User.objects.get(username__exact = u_name) + profile = current_user.get_profile() + if profile.dob != dob: + raise forms.ValidationError("Date of Birth doesn't match.") + except User.DoesNotExist: + raise forms.ValidationError("Correct the following errors and try logging in again.") + + + ##Authentication part + user = authenticate(username = u_name, password = pwd) + if not user: + raise forms.ValidationError("Application Number or Registration Number doesn't match.") + return user + + +class UserDetailsForm(forms.Form): + + def __init__(self, user, *args, **kwargs): + self.user = user + super(UserDetailsForm, self).__init__(*args, **kwargs) + + email = forms.EmailField(label="Email Address", + help_text="Enter a valid email id if you have any.") + phone_number = forms.IntegerField(label="Phone number", + help_text="10 digit number with code") + + + def clean_phone_number(self): + pno = self.cleaned_data['phone_number'] + if str(pno).strip(digits) or len(str(pno)) != 10: + raise forms.ValidationError("Not a valid phone number") + return pno + + def save(self): + cleaned_data = self.cleaned_data + user_profile = self.user.get_profile() + + user_profile.secondary_email = self.cleaned_data['email'] + user_profile.phone_number = self.cleaned_data['phone_number'] + + user_profile.save() + + diff --git a/choice_seeker/allotter/management/__init__.py b/choice_seeker/allotter/management/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/choice_seeker/allotter/management/commands/__init__.py b/choice_seeker/allotter/management/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/choice_seeker/allotter/management/commands/loadexam.py b/choice_seeker/allotter/management/commands/loadexam.py new file mode 100644 index 0000000..2fedb66 --- /dev/null +++ b/choice_seeker/allotter/management/commands/loadexam.py @@ -0,0 +1,40 @@ +from csv import reader +from django.core.management.base import BaseCommand, CommandError +from allotter.models import Exam + +class Command(BaseCommand): + args = '' + help = "Give the filename of the csv file that has all the exam code and exam name relation" + + def handle(self, *args, **options): + + clean_exam() + + for fname in args: + load_exam(fname) + + self.stdout.write('Done\n') + + +def clean_exam(): + """Removes all the objects from the database, required as if not done there might be a case of multile entries""" + data = Exam.objects.all() + data.delete() + +def load_exam(filename): + """Load exam code and exam name from the given csv file. The file should + declare a list of "exam_code;exam_name". + """ + try: + csvFile = open(filename, 'rb') + except IOError as (errno,strerror): + print "I/O error({0}): {1}".format(errno, strerror) + + csvReader = reader(csvFile, delimiter=";") + + for data in csvReader: + new_exam = Exam.objects.create() + new_exam.exam_code = data[0] + new_exam.exam_name = data[1] + new_exam.save() + print "Added ({0} : {1})".format(data[0], data[1]) \ No newline at end of file diff --git a/choice_seeker/allotter/management/commands/loadoptions.py b/choice_seeker/allotter/management/commands/loadoptions.py new file mode 100644 index 0000000..f7c01e6 --- /dev/null +++ b/choice_seeker/allotter/management/commands/loadoptions.py @@ -0,0 +1,60 @@ +from optparse import make_option +from csv import reader +from django.core.management.base import BaseCommand +from allotter.models import Exam, Option + +class Command(BaseCommand): + option_list = BaseCommand.option_list + ( + make_option('--pcc',metavar='Paper course code file name', type=str), + make_option('--cc',metavar='Course code file name', type=str), + ) + help = "Give the filenames of the csv files that has all the option code, name and exam code relation" + + def handle(self, *args, **options): + + clean_option() + + load_option(options) + + self.stdout.write('Done\n') + + +def clean_option(): + """Removes all the objects from the database, required as if not done there might be a case of multiple entries""" + data = Option.objects.all() + data.delete() + +def load_option(options): + """Load option code and option name from the given csv file. The file should + declare a list of "exam_code,option_code,option,code". + """ + paperCourseFileName=options.get('pcc') + courseCodeFileName=options.get('cc') + try: + paperCourseFile = open(paperCourseFileName, 'rb') + except IOError as (errno,strerror): + print "I/O error({0}): {1}".format(errno, strerror) + + try: + courseCodeFile = open(courseCodeFileName, 'rb') + except IOError as (errno,strerror): + print "I/O error({0}): {1}".format(errno, strerror) + + paperReader = reader(paperCourseFile, delimiter=",") + courseReader = reader(courseCodeFile, delimiter=",") + + courseDict = {} + + for data in courseReader: + courseDict[int(data[0])]=data[1] + + for data in paperReader: + exam = Exam.objects.get(exam_code=data[0]) + for value in data[1:len(data)]: + try: + new_option = Option.objects.get(opt_code=value) + except Option.DoesNotExist: + new_option = Option(opt_name=courseDict[int(value)],opt_code=value) + new_option.save() + new_option.exam.add(exam) + print "Added (option {0} with code {1} and exam {2})".format(courseDict[int(value)],value,exam) \ No newline at end of file diff --git a/choice_seeker/allotter/management/commands/loadusers.py b/choice_seeker/allotter/management/commands/loadusers.py new file mode 100644 index 0000000..99fd075 --- /dev/null +++ b/choice_seeker/allotter/management/commands/loadusers.py @@ -0,0 +1,65 @@ +from optparse import make_option +from datetime import datetime +from csv import DictReader +from django.core.management.base import BaseCommand +from allotter.models import Exam, Application, User, Profile + +class Command(BaseCommand): + option_list = BaseCommand.option_list + ( + make_option('--usdf',metavar='User details file name', type=str), + ) + help = "Give the filename of the csv files that has all the details of the users" + + def handle(self, *args, **options): + + clean_users() + + load_users(options) + + self.stdout.write('Done\n') + + +def clean_users(): + """Removes all the objects from the database, required as if not done there might be a case of multiple entries""" + User.objects.filter(is_superuser=False).delete() + +def load_users(options): + """Load option code and option name from the given csv file. The file should + declare a list of "exam_code,option_code,option,code". + """ + userDetailsFileName=options.get('usdf') + try: + userDetailsFile = open(userDetailsFileName, 'rb') + except IOError as (errno,strerror): + print "I/O error({0}): {1}".format(errno, strerror) + + + userReader = DictReader(userDetailsFile, delimiter=":") + + + for data in userReader: + appno = data['AppNo.'] + regno = data['Reg.No.'] + new_user = User.objects.create_user(regno, password=appno, email="") + application = Application(user=new_user) + application.np = int(data['NP']) + if data['P1'].strip(): + application.first_paper = Exam.objects.get(exam_code=data['P1']) + try: + application.second_paper = Exam.objects.get(exam_code=data['P2']) + except: + pass + else: + application.first_paper = Exam.objects.get(exam_code=data['P2']) + + + application.nat = data['Nat'] + application.gender = data['Gdr'] + application.cent = data['Cent'] + application.cgy = data['Cgy'] + application.save() + dob = datetime.strptime(data['DOB'], "%d/%m/%y") + new_profile = Profile(user=new_user, application=application) + new_profile.dob = dob + new_profile.save() + print "Added user with {0} and {1} with dob as {2}".format(appno,regno,dob) \ No newline at end of file diff --git a/choice_seeker/allotter/models.py b/choice_seeker/allotter/models.py new file mode 100644 index 0000000..9da8213 --- /dev/null +++ b/choice_seeker/allotter/models.py @@ -0,0 +1,136 @@ +from django.db import models +from django.contrib.auth.models import User + +##EXAMINATION_SUBJECTS = ( +## ("Physics", "Physics"), +## ("Mathematics", "Mathematics"), +## ("Chemistry", "Chemistry"), +## ) + +##CATEGORIES = ( +## ("GEN", "GEN"), +## ("OBC", "OBC(Non-Creamy Layer)"), +## ("SC", "SC"), +## ("ST", "ST"), +## ) + +##AVAILABLE_OPTIONS = ( +## ("MScChem", "M.Sc Chemisty"), +## ("M.Sc-Physics-IIT-Bombay", "M.Sc Physics IIT Bombay"), +## ("MScMath","M.Sc Mathematics"), +## ("MscHist", "M.Sc History"), +## ("MSc-PhD Dual-Degree-IIT-Bombay", "MSc-PhD Dual Degree IIT Bombay"), +## ("M.Sc Physics-IIT-Madras", "M.Sc Physics IIT Madras"), +## ("M.Sc-Physics-IIT-Guwahati", "M.Sc Physics IIT Guwahati"), +## ("M.Sc-Physics-IIT-KGP", "M.Sc Physics IIT KGP"), +## ("M.Sc-Physics-IIT-Roorkee", "M.Sc Physics IIT Roorkee"), +##) + +##GENDER_CHOICES = ( +## ("M", "Male"), +## ("F", "Female"),) + +##APPLICATION_STATUS = ( +## ("I", "Incomplete"), +## ("Submitted", "Submitted")) + +##BIRTH_YEAR_CHOICES = ('1989', '1990', '1991') + +class Exam(models.Model): + """ + Table for Examination Codes and Subject names. + """ + ##PH for Physics, CY for Chemistry + exam_code = models.CharField(max_length=100, + verbose_name=u"Test Paper code", + help_text=u"Unique code for the Test") + + exam_name = models.CharField(max_length=100, + verbose_name=u"Test Paper", + help_text=u"Subject name of the Test") + + def __unicode__(self): + return self.exam_name + + +class Option(models.Model): + """ + Options Table, Foreign Keyed with Examination. + """ + + opt_name = models.CharField(max_length=100, + verbose_name=u"Programme name", + help_text=u"Programme Title") + + opt_code = models.IntegerField(max_length=3, + verbose_name=u"Programme Code") + + opt_location = models.CharField(max_length=30, + verbose_name=u"Programme Location", + help_text=u"Offered by which IIT") + + exam = models.ManyToManyField(Exam) + + class Meta: + verbose_name_plural = "Options" + + def __unicode__(self): + return unicode(self.opt_code) + + +class Application(models.Model): + """An application for the student - one per student + """ + user = models.OneToOneField(User) + + ##To be filled by applicant + options_selected = models.CharField(max_length=5000,help_text="CSV formatted list of options", blank=True) + + ##Prefilled fields + np = models.IntegerField(max_length=2, help_text="Number of Test Papers") + + ##Mandatory First Subject + first_paper = models.ForeignKey(Exam, related_name="first_paper") + + ##Second subject can be left blank or null + second_paper = models.ForeignKey(Exam, related_name="second_paper", blank=True, null=True) + + nat = models.CharField(max_length=10, verbose_name="Nationality") + + gender = models.CharField(max_length=2, verbose_name="Gender") + + cent = models.IntegerField(max_length=10, verbose_name="Center Code") + + cgy = models.CharField(max_length=10, verbose_name="Category") + + pd = models.BooleanField(verbose_name="Physical Disability", default=False, blank=True) + + submitted = models.BooleanField(verbose_name="Submission Status", default=False) + + def __unicode__(self): + u = self.user + return u'Application for {0}'.format(u.username) + +class Profile(models.Model): + + user = models.OneToOneField(User) + + #Used for verification purposes + dob = models.DateField(verbose_name=u"Date of Birth", + help_text=u"Date of birth as given in the application") + + secondary_email = models.EmailField(verbose_name=u"Secondary Email", + help_text=u"Email address read from user after authentication") + + phone_number = models.IntegerField(max_length=10, verbose_name="Phone Number", + help_text=u"Phone number read from user after authentication") + + #Application for the Profile + application = models.ForeignKey(Application) + + def __unicode__(self): + u = self.user + return u'User Profile {0}'.format(u.username) + + + diff --git a/choice_seeker/allotter/templatetags/__init__.py b/choice_seeker/allotter/templatetags/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/choice_seeker/allotter/templatetags/range_filter.py b/choice_seeker/allotter/templatetags/range_filter.py new file mode 100644 index 0000000..1ce43d8 --- /dev/null +++ b/choice_seeker/allotter/templatetags/range_filter.py @@ -0,0 +1,27 @@ +##Credits : http://djangosnippets.org/snippets/1357/ + +from django.template import Library + +register = Library() + +@register.filter +def get_range( value ): + """ + Filter - returns a list containing range made from given value + Usage (in template): + +
    {% for i in 3|get_range %} +
  • {{ i }}. Do something
  • + {% endfor %}
+ + Results with the HTML: +
    +
  • 0. Do something
  • +
  • 1. Do something
  • +
  • 2. Do something
  • +
+ + Instead of 3 one may use the variable set in the views + """ + return range( value ) + diff --git a/choice_seeker/allotter/tests.py b/choice_seeker/allotter/tests.py new file mode 100644 index 0000000..501deb7 --- /dev/null +++ b/choice_seeker/allotter/tests.py @@ -0,0 +1,16 @@ +""" +This file demonstrates writing tests using the unittest module. These will pass +when you run "manage.py test". + +Replace this with more appropriate tests for your application. +""" + +from django.test import TestCase + + +class SimpleTest(TestCase): + def test_basic_addition(self): + """ + Tests that 1 + 1 always equals 2. + """ + self.assertEqual(1 + 1, 2) diff --git a/choice_seeker/allotter/urls.py b/choice_seeker/allotter/urls.py new file mode 100644 index 0000000..6556c62 --- /dev/null +++ b/choice_seeker/allotter/urls.py @@ -0,0 +1,11 @@ +from django.conf.urls.defaults import patterns, url + +urlpatterns = patterns('allotter.views', + url(r'^login/$', 'user_login'), + url(r'^logout/$', 'user_logout'), + url(r'^(?P\d+)/apply/$', 'apply'), + url(r'^(?P\d+)/details/$', 'submit_details'), + url(r'^(?P\d+)/get_pdf/$', 'generate_pdf'), + url(r'^(?P\d+)/submit/$', 'submit_options', name='submit_options'), + url(r'^(?P\d+)/complete/$', 'complete_allotment', name='complete_allotment'), +) diff --git a/choice_seeker/allotter/views.py b/choice_seeker/allotter/views.py new file mode 100644 index 0000000..fb819fc --- /dev/null +++ b/choice_seeker/allotter/views.py @@ -0,0 +1,260 @@ +from django.contrib.auth import login, logout, authenticate +from django.contrib.auth.decorators import login_required +from django.shortcuts import render, redirect, get_object_or_404 + +from django.http import Http404 +from django.http import HttpResponse +from django.http import HttpResponseRedirect + +from django.core.urlresolvers import reverse + +from django.contrib.auth.models import User +from allotter.models import Profile, Option, Exam +from allotter.forms import UserLoginForm, UserDetailsForm + +from itertools import chain + +#Reportlab libraries +from reportlab.platypus import Table, TableStyle, SimpleDocTemplate, Paragraph, Spacer +from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle +from reportlab.lib import colors +from reportlab.lib.units import inch +from reportlab.lib.enums import TA_JUSTIFY + +import time + +def user_login(request): + """ + Verify the user credentials and log the user in. + """ + + user = request.user + if user.is_authenticated(): + status = user.get_profile().application.submitted #Getting the submission status + if status: #If already submitted, takes to Completion Page + return HttpResponseRedirect(reverse('allotter.views.complete_allotment', args=(user.username,))) + else: #Otherwise to Option Choosing Page + return HttpResponseRedirect(reverse('allotter.views.apply', args=(user.username,))) + + if request.method == "POST": + form = UserLoginForm(request.POST) + if form.is_valid(): + user = form.cleaned_data + login(request, user) + status = user.get_profile().application.submitted #Getting the submission status + if status: + return HttpResponseRedirect(reverse('allotter.views.complete_allotment', args=(user.username,))) + else: + return HttpResponseRedirect(reverse('allotter.views.submit_details', args=(user.username,))) + else: + context = {"form": form} + return render(request, 'allotter/login.html', context) + else: + form = UserLoginForm() + context = {"form": form} + return render(request, 'allotter/login.html', context) + + +@login_required +def submit_details(request, reg_no): + """ + Get the secondary email address, phone number and save it to the Profile. + """ + user = request.user + + if request.method == "POST": + form = UserDetailsForm(user, request.POST) + if form.is_valid(): + data = form.cleaned_data + form.save() + return redirect("/allotter/apply/") + else: + return render(request, 'allotter/details.html', {'form':form}) + + else: + form = UserDetailsForm(request.user) + context = {"form": form} + return render(request, 'allotter/details.html', context) + +def get_details(user, error_message = ""): + """ + Retrieves the information about Test paper(s) and options available + and returns them in a dictionary(context) for passing to the Template. + """ + user_profile = user.get_profile() + user_application = user_profile.application + np = user_application.np #Number of Papers + first_paper = user_application.first_paper #First Paper Name + options_available_first = Option.objects.filter(exam__exam_name=first_paper).distinct() #Options for First paper + oafl = len(options_available_first) + if np == 2: #If written two exams + second_paper = user_application.second_paper + options_available_second = Option.objects.filter(exam__exam_name=second_paper).distinct() + oasl = len(options_available_second) + context = {'user': user, 'first_paper': first_paper, + 'options_available_first' : options_available_first, + 'second_paper': second_paper, + 'options_available_second' : options_available_second, + 'np' : np, 'options_range': range(1, oafl + oasl + 1, 1), + 'error_message': error_message} + else: #If written only one exam + context = {'user': user, 'first_paper': first_paper, + 'options_available_first' : options_available_first, + 'options_range': range(1, oafl + 1, 1), + 'np' : np, 'error_message' : error_message} + return context + +@login_required +def apply(request, reg_no): + """ + Displays the application page for an authenticated user. + """ + user = request.user + if not(user.is_authenticated()): + return redirect('/allotter/login/') + + context = get_details(user) + + return render(request, 'allotter/apply.html', context) + + +def user_logout(request): + ##Logouts the user. + logout(request) + return redirect ('/allotter/login/') + +#TODO: Extensive Testing + +@login_required +def submit_options(request, reg_no): + """ + Gets the Options and their preference number through the POST object and + stores them as list(sorted according to preferences). Options with None are + ignored. + """ + user = get_object_or_404(User, username=reg_no) + user_profile = user.get_profile() + user_application = user_profile.application + np = user_application.np + first_paper = user_application.first_paper #First Paper Name + options_available_first = Option.objects.filter(exam__exam_name=first_paper).distinct() #Options for First paper + + if np == 2: #If qualified for second paper + second_paper = user_application.second_paper #Second Paper Name + options_available_second = Option.objects.filter(exam__exam_name=second_paper).distinct() #Options for second paper + options_available_list = chain(options_available_first, options_available_second) #chaining the two lists + else: + options_available_list = options_available_first + + options_chosen_list = [] #Initializing empty list for storing options + for option in options_available_list: + option_pref = request.POST[unicode(option.opt_code)] + options_chosen_list.append([option_pref, str(option.opt_code)]) #[preference, option code] + + options_chosen_list.sort() #Sorting by preference + options_code_list = [] + for opt in options_chosen_list: + if int(opt[0]): #ignoring the options for which None was marked + options_code_list.append(opt[1]) + + user_application.options_selected = options_code_list #Saving the data in model + user_application.submitted = True #Submission Status + user_application.save() + return HttpResponseRedirect(reverse('allotter.views.complete_allotment', args=(reg_no,))) + +def complete_allotment(request, reg_no): + """ + Passes the chosen options queryset to the Completion Page Template + """ + user = get_object_or_404(User, username=reg_no) + sec_email = user.get_profile().secondary_email + options_chosen = get_chosen_options(user) + context = {'username': reg_no, 'email': sec_email, + 'options_chosen': options_chosen} + + return render(request, 'allotter/complete.html', context) + + +def get_chosen_options(user): + """ + Reads the options submitted by the user in the Application page + """ + user_profile = user.get_profile() + user_application = user_profile.application + np = user_application.np + ocl = eval(user_application.options_selected) + chosen_options = [] + for oc in ocl: + chosen_options.append(Option.objects.get(opt_code=int(oc))) + return chosen_options + + +@login_required +def generate_pdf(request, reg_no): + """ + The Ugly code for generating the pdf using ReportLab. + """ + + user = get_object_or_404(User, username=reg_no) + user_profile = user.get_profile() + user_application = user_profile.application + np = user_application.np + + response = HttpResponse(mimetype='application/pdf') + response['Content-Disposition'] = 'attachment; filename=JAM2012_Allottment.pdf' + + elements = [] + doc = SimpleDocTemplate(response) + + formatted_time = time.ctime() + styles = getSampleStyleSheet() + styles.add(ParagraphStyle(name='Justify', alignment=TA_JUSTIFY)) + + ptext = 'JAM 2012 Allotment.' + elements.append(Paragraph(ptext, styles["Justify"])) + elements.append(Spacer(4, 20)) + + ptext = 'Registration Number: %s' % reg_no + elements.append(Paragraph(ptext, styles["Normal"])) + elements.append(Spacer(1, 12)) + + ptext = 'Number of Papers Eligible: %s' % np + elements.append(Paragraph(ptext, styles["Normal"])) + elements.append(Spacer(1, 12)) + + ptext = 'No options were chosen.' + elements.append(Paragraph(ptext, styles["Normal"])) + elements.append(Spacer(1, 12)) + + data = [] + options = get_chosen_options(user) ##Put a check to show when the options chosen is empty + + if not(options): + doc.build(elements) + return response + + ptext = 'Following are the options in order of preference' + elements.append(Paragraph(ptext, styles["Normal"])) + elements.append(Spacer(1, 12)) + + counter = 1 + for opt in options: + data.append([counter, opt.opt_code, opt.opt_location, opt.opt_name]) + counter = counter + 1 + + t = Table(data) + t.setStyle(TableStyle([('GRID',(0,0),(3,len(options)),1,colors.black), + ('TEXTCOLOR',(0,0),(0,-1),colors.green)])) + + elements.append(t) + + ptext = '%s' % formatted_time + elements.append(Paragraph(ptext, styles["Normal"])) + elements.append(Spacer(1, 12)) + + doc.build(elements) + + return response + + + diff --git a/choice_seeker/manage.py b/choice_seeker/manage.py new file mode 100755 index 0000000..3e4eedc --- /dev/null +++ b/choice_seeker/manage.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python +from django.core.management import execute_manager +import imp +try: + imp.find_module('settings') # Assumed to be in the same directory. +except ImportError: + import sys + sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n" % __file__) + sys.exit(1) + +import settings + +if __name__ == "__main__": + execute_manager(settings) diff --git a/choice_seeker/settings.py b/choice_seeker/settings.py new file mode 100644 index 0000000..dd71bc4 --- /dev/null +++ b/choice_seeker/settings.py @@ -0,0 +1,182 @@ +# Django settings for aloha project. + +import os +PROJECT_DIR = os.path.dirname(__file__) + +DEBUG = True +TEMPLATE_DEBUG = DEBUG + +ADMINS = ( + ('Primal Pappachan', 'primal@fossee.in'), +) + +AUTHORS = ( + ('Primal Pappachan', 'primal@fossee.in'), + ('Parth Buch', 'parth@fossee.in'), +) + +MANAGERS = ADMINS + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. + 'NAME': 'jam', # Or path to database file if using sqlite3. + 'USER': '', # Not used with sqlite3. + 'PASSWORD': '', # Not used with sqlite3. + 'HOST': '', # Set to empty string for localhost. Not used with sqlite3. + 'PORT': '', # Set to empty string for default. Not used with sqlite3. + } +} + +URL_ROOT = '' + +# Local time zone for this installation. Choices can be found here: +# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name +# although not all choices may be available on all operating systems. +# On Unix systems, a value of None will cause Django to use the same +# timezone as the operating system. +# If running in a Windows environment this must be set to the same as your +# system time zone. +TIME_ZONE = 'Asia/Kolkata' + +# Language code for this installation. All choices can be found here: +# http://www.i18nguy.com/unicode/language-identifiers.html +LANGUAGE_CODE = 'en-us' + +SITE_ID = 1 + +# If you set this to False, Django will make some optimizations so as not +# to load the internationalization machinery. +USE_I18N = True + +# If you set this to False, Django will not format dates, numbers and +# calendars according to the current locale +USE_L10N = True + +# Absolute filesystem path to the directory that will hold user-uploaded files. +# Example: "/home/media/media.lawrence.com/media/" +MEDIA_ROOT = '' + +# URL that handles the media served from MEDIA_ROOT. Make sure to use a +# trailing slash. +# Examples: "http://media.lawrence.com/media/", "http://example.com/media/" +MEDIA_URL = '' + +# Absolute path to the directory static files should be collected to. +# Don't put anything in this directory yourself; store your static files +# in apps' "static/" subdirectories and in STATICFILES_DIRS. +# Example: "/home/media/media.lawrence.com/static/" +STATIC_ROOT = os.path.join(PROJECT_DIR, "static") + +# URL prefix for static files. +# Example: "http://media.lawrence.com/static/" +STATIC_URL = '/static/' + +# URL prefix for admin static files -- CSS, JavaScript and images. +# Make sure to use a trailing slash. +# Examples: "http://foo.com/static/admin/", "/static/admin/". +ADMIN_MEDIA_PREFIX = '/static/admin/' + +# Additional locations of static files +STATICFILES_DIRS = ( + # Put strings here, like "/home/html/static" or "C:/www/django/static". + # Always use forward slashes, even on Windows. + # Don't forget to use absolute paths, not relative paths. +) + +# List of finder classes that know how to find static files in +# various locations. +STATICFILES_FINDERS = ( + 'django.contrib.staticfiles.finders.FileSystemFinder', + 'django.contrib.staticfiles.finders.AppDirectoriesFinder', +# 'django.contrib.staticfiles.finders.DefaultStorageFinder', +) + +# Make this unique, and don't share it with anybody. +SECRET_KEY = '5(yt_egghk$&w1qsxy9remz^+!^5m-99gf$9+yam^56xt2#7&$' + +# List of callables that know how to import templates from various sources. +TEMPLATE_LOADERS = ( + 'django.template.loaders.filesystem.Loader', + 'django.template.loaders.app_directories.Loader', +# 'django.template.loaders.eggs.Loader', +) + +MIDDLEWARE_CLASSES = ( + 'django.middleware.common.CommonMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'debug_toolbar.middleware.DebugToolbarMiddleware', +) + +ROOT_URLCONF = 'aloha.urls' + +TEMPLATE_DIRS = ( + # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". + # Always use forward slashes, even on Windows. + # Don't forget to use absolute paths, not relative paths. + os.path.join(PROJECT_DIR, "template") +) + +INSTALLED_APPS = ( + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.sites', + 'django.contrib.messages', + 'django.contrib.staticfiles', + # Uncomment the next line to enable the admin: + 'django.contrib.admin', + # Uncomment the next line to enable admin documentation: + # 'django.contrib.admindocs', + #Third-Party Apps + 'south', + 'django_extensions', + 'debug_toolbar', + + 'allotter', +) + + +# A sample logging configuration. The only tangible logging +# performed by this configuration is to send an email to +# the site admins on every HTTP 500 error. +# See http://docs.djangoproject.com/en/dev/topics/logging for +# more details on how to customize your logging configuration. +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'handlers': { + 'mail_admins': { + 'level': 'ERROR', + 'class': 'django.utils.log.AdminEmailHandler' + } + }, + 'loggers': { + 'django.request': { + 'handlers': ['mail_admins'], + 'level': 'ERROR', + 'propagate': True, + }, + } +} + +AUTH_PROFILE_MODULE = "allotter.Profile" +LOGIN_URL = '/allotter/login' + +#For developing locally +INTERNAL_IPS = ('127.0.0.1') + +DEBUG_TOOLBAR_PANELS = ( + 'debug_toolbar.panels.version.VersionDebugPanel', + 'debug_toolbar.panels.timer.TimerDebugPanel', + 'debug_toolbar.panels.settings_vars.SettingsVarsDebugPanel', + 'debug_toolbar.panels.headers.HeaderDebugPanel', + 'debug_toolbar.panels.request_vars.RequestVarsDebugPanel', + 'debug_toolbar.panels.template.TemplateDebugPanel', + 'debug_toolbar.panels.sql.SQLDebugPanel', + 'debug_toolbar.panels.signals.SignalDebugPanel', + 'debug_toolbar.panels.logger.LoggingPanel', +) diff --git a/choice_seeker/template/allotter/apply.html b/choice_seeker/template/allotter/apply.html new file mode 100644 index 0000000..201e1f2 --- /dev/null +++ b/choice_seeker/template/allotter/apply.html @@ -0,0 +1,109 @@ +{% extends "base.html" %} + +{% load range_filter %} + +{% block title %} JAM 2012 Application form {% endblock %} + +{% block content %} + +

Welcome to JAM 2012 allotment!

+ +

Read the following instructions carefully before continuing.

+ +
+Choose the options as per your preference + +

You are eligible for {{first_paper}} + +{% comment %} +Checking if there is second paper and displaying its name. +{% endcomment %} + +{% if np == 2 %} + +and {{second_paper}} + +{% endif %} + +

+ +

For the paper(s) in which you are in the merit list, the following +options are available to you. Please rank your choices.

+ +

Preferences will be assigned to options in the ascending order. Make sure it's +None for all options after your last option(so that it is not considered).

+ +
+ +{% comment %} + +Listing the options for first test paper. +{% endcomment %} + +

Options available for {{first_paper}}

+ +{% if error_message %}

{{ error_message }}

{% endif %} + +
+{% csrf_token %} + + + + + + + + + +{% for option in options_available_first %} + + + + + + +{% endfor %} +

Programme Code

Programme Name

Insitute

Preference

{{ option.opt_code }}

{{option.opt_name }}

{{option.opt_location }}

+
+ +{% if np == 2 %} + +

Options available for {{second_paper}}

+ + + + + + + + + +{% for option in options_available_second %} + + + + + + +{% endfor %} +

Programme Code

Programme Name

Insitute

Preference

{{option.opt_code }}

{{option.opt_name }}

{{option.opt_location }}

+
+ +{% endif %} + +

+

+ +
+ +{% endblock content %} diff --git a/choice_seeker/template/allotter/complete.html b/choice_seeker/template/allotter/complete.html new file mode 100644 index 0000000..26ee46d --- /dev/null +++ b/choice_seeker/template/allotter/complete.html @@ -0,0 +1,60 @@ +{% extends "base.html" %} + +{% block title %}Options saved.{% endblock %} + +{% block content %} + +

The following options have been saved. Please verify them before logging out.

+ +

Please keep in mind that, the next time you login you will be redirected to this page straightaway.

+ +{% if options_chosen %} + + + + + + + + +{% for option in options_chosen %} + + + + + + +{% endfor %} + +

Programme Code

Programme Name

Insitute

Preference

{{ forloop.counter }}

{{ option.opt_code }}

{{ option.opt_name }}

{{ option.opt_location }}

+ +{% if email %} + +An email with the list of options has been sent {{ email }} for book-keeping purposes. + +{% endif %} + +{% else %} + +

No Options were chosen, Press Edit Options to go back and select options otherwise Press logout to exit the allotment process

+ +{% endif %} + +
+{% csrf_token %} + +
+ +
+{% csrf_token %} + +
+ +
+{% csrf_token %} + +
+ +{% endblock content %} + + diff --git a/choice_seeker/template/allotter/details.html b/choice_seeker/template/allotter/details.html new file mode 100644 index 0000000..5beeb85 --- /dev/null +++ b/choice_seeker/template/allotter/details.html @@ -0,0 +1,19 @@ +{% extends "base.html" %} + +{% block title %}Details form {% endblock %} + +{% block content %} +Please provide the following details. +
+{% csrf_token %} + + +{{ form.as_table }} +
+ +

These details cannot be changed once entered.

+ + +
+ +{% endblock content %} diff --git a/choice_seeker/template/allotter/hello.html b/choice_seeker/template/allotter/hello.html new file mode 100644 index 0000000..0d07c7f --- /dev/null +++ b/choice_seeker/template/allotter/hello.html @@ -0,0 +1,11 @@ +{% extends "base.html" %} + +{% block title %} Welcome Note {% endblock %} + +{% block content %} +

Hello, there

+ +

Welcome {{user.first_name.title}} {{user.last_name.title}}, +to JAM 2012 allotment!

+ +{% endblock content %} diff --git a/choice_seeker/template/allotter/login.html b/choice_seeker/template/allotter/login.html new file mode 100644 index 0000000..72769a0 --- /dev/null +++ b/choice_seeker/template/allotter/login.html @@ -0,0 +1,21 @@ +{% extends "base.html" %} + +{% block title %}Login{% endblock title %} + +{% block content %} +

Welcome to the Allotment. +Please login to proceed.

+ +
+{% csrf_token %} + + +{{ form.as_table }} +
+ +
+ +
+ + +{% endblock content %} diff --git a/choice_seeker/template/allotter/register.html b/choice_seeker/template/allotter/register.html new file mode 100644 index 0000000..d7d04b9 --- /dev/null +++ b/choice_seeker/template/allotter/register.html @@ -0,0 +1,17 @@ +{% extends "base.html" %} + +{% block title %}Registration form {% endblock %} + +{% block content %} +Please provide the following details. +
+{% csrf_token %} + + +{{ form.as_table }} +
+ + +
+ +{% endblock content %} diff --git a/choice_seeker/template/base.html b/choice_seeker/template/base.html new file mode 100644 index 0000000..cd937ba --- /dev/null +++ b/choice_seeker/template/base.html @@ -0,0 +1,23 @@ + + + + + {% block title %} {% endblock %} + + + + + +
+ {% block content %}{% endblock %} + {% block main_content %}{% endblock %} +
+ + diff --git a/choice_seeker/urls.py b/choice_seeker/urls.py new file mode 100644 index 0000000..f5fdfe0 --- /dev/null +++ b/choice_seeker/urls.py @@ -0,0 +1,18 @@ +from django.conf.urls.defaults import patterns, include, url + +from django.contrib import admin + +admin.autodiscover() + +urlpatterns = patterns('', + url(r'^allotter/', include('allotter.urls')), + # Examples: + # url(r'^$', 'aloha.views.home', name='home'), + # url(r'^aloha/', include('aloha.foo.urls')), + + # Uncomment the admin/doc line below to enable admin documentation: + # url(r'^admin/doc/', include('django.contrib.admindocs.urls')), + + # Uncomment the next line to enable the admin: + url(r'^admin/', include(admin.site.urls)), +) diff --git a/manage.py b/manage.py deleted file mode 100755 index 3e4eedc..0000000 --- a/manage.py +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env python -from django.core.management import execute_manager -import imp -try: - imp.find_module('settings') # Assumed to be in the same directory. -except ImportError: - import sys - sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n" % __file__) - sys.exit(1) - -import settings - -if __name__ == "__main__": - execute_manager(settings) diff --git a/settings.py b/settings.py deleted file mode 100644 index dd71bc4..0000000 --- a/settings.py +++ /dev/null @@ -1,182 +0,0 @@ -# Django settings for aloha project. - -import os -PROJECT_DIR = os.path.dirname(__file__) - -DEBUG = True -TEMPLATE_DEBUG = DEBUG - -ADMINS = ( - ('Primal Pappachan', 'primal@fossee.in'), -) - -AUTHORS = ( - ('Primal Pappachan', 'primal@fossee.in'), - ('Parth Buch', 'parth@fossee.in'), -) - -MANAGERS = ADMINS - -DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. - 'NAME': 'jam', # Or path to database file if using sqlite3. - 'USER': '', # Not used with sqlite3. - 'PASSWORD': '', # Not used with sqlite3. - 'HOST': '', # Set to empty string for localhost. Not used with sqlite3. - 'PORT': '', # Set to empty string for default. Not used with sqlite3. - } -} - -URL_ROOT = '' - -# Local time zone for this installation. Choices can be found here: -# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name -# although not all choices may be available on all operating systems. -# On Unix systems, a value of None will cause Django to use the same -# timezone as the operating system. -# If running in a Windows environment this must be set to the same as your -# system time zone. -TIME_ZONE = 'Asia/Kolkata' - -# Language code for this installation. All choices can be found here: -# http://www.i18nguy.com/unicode/language-identifiers.html -LANGUAGE_CODE = 'en-us' - -SITE_ID = 1 - -# If you set this to False, Django will make some optimizations so as not -# to load the internationalization machinery. -USE_I18N = True - -# If you set this to False, Django will not format dates, numbers and -# calendars according to the current locale -USE_L10N = True - -# Absolute filesystem path to the directory that will hold user-uploaded files. -# Example: "/home/media/media.lawrence.com/media/" -MEDIA_ROOT = '' - -# URL that handles the media served from MEDIA_ROOT. Make sure to use a -# trailing slash. -# Examples: "http://media.lawrence.com/media/", "http://example.com/media/" -MEDIA_URL = '' - -# Absolute path to the directory static files should be collected to. -# Don't put anything in this directory yourself; store your static files -# in apps' "static/" subdirectories and in STATICFILES_DIRS. -# Example: "/home/media/media.lawrence.com/static/" -STATIC_ROOT = os.path.join(PROJECT_DIR, "static") - -# URL prefix for static files. -# Example: "http://media.lawrence.com/static/" -STATIC_URL = '/static/' - -# URL prefix for admin static files -- CSS, JavaScript and images. -# Make sure to use a trailing slash. -# Examples: "http://foo.com/static/admin/", "/static/admin/". -ADMIN_MEDIA_PREFIX = '/static/admin/' - -# Additional locations of static files -STATICFILES_DIRS = ( - # Put strings here, like "/home/html/static" or "C:/www/django/static". - # Always use forward slashes, even on Windows. - # Don't forget to use absolute paths, not relative paths. -) - -# List of finder classes that know how to find static files in -# various locations. -STATICFILES_FINDERS = ( - 'django.contrib.staticfiles.finders.FileSystemFinder', - 'django.contrib.staticfiles.finders.AppDirectoriesFinder', -# 'django.contrib.staticfiles.finders.DefaultStorageFinder', -) - -# Make this unique, and don't share it with anybody. -SECRET_KEY = '5(yt_egghk$&w1qsxy9remz^+!^5m-99gf$9+yam^56xt2#7&$' - -# List of callables that know how to import templates from various sources. -TEMPLATE_LOADERS = ( - 'django.template.loaders.filesystem.Loader', - 'django.template.loaders.app_directories.Loader', -# 'django.template.loaders.eggs.Loader', -) - -MIDDLEWARE_CLASSES = ( - 'django.middleware.common.CommonMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'debug_toolbar.middleware.DebugToolbarMiddleware', -) - -ROOT_URLCONF = 'aloha.urls' - -TEMPLATE_DIRS = ( - # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". - # Always use forward slashes, even on Windows. - # Don't forget to use absolute paths, not relative paths. - os.path.join(PROJECT_DIR, "template") -) - -INSTALLED_APPS = ( - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.sites', - 'django.contrib.messages', - 'django.contrib.staticfiles', - # Uncomment the next line to enable the admin: - 'django.contrib.admin', - # Uncomment the next line to enable admin documentation: - # 'django.contrib.admindocs', - #Third-Party Apps - 'south', - 'django_extensions', - 'debug_toolbar', - - 'allotter', -) - - -# A sample logging configuration. The only tangible logging -# performed by this configuration is to send an email to -# the site admins on every HTTP 500 error. -# See http://docs.djangoproject.com/en/dev/topics/logging for -# more details on how to customize your logging configuration. -LOGGING = { - 'version': 1, - 'disable_existing_loggers': False, - 'handlers': { - 'mail_admins': { - 'level': 'ERROR', - 'class': 'django.utils.log.AdminEmailHandler' - } - }, - 'loggers': { - 'django.request': { - 'handlers': ['mail_admins'], - 'level': 'ERROR', - 'propagate': True, - }, - } -} - -AUTH_PROFILE_MODULE = "allotter.Profile" -LOGIN_URL = '/allotter/login' - -#For developing locally -INTERNAL_IPS = ('127.0.0.1') - -DEBUG_TOOLBAR_PANELS = ( - 'debug_toolbar.panels.version.VersionDebugPanel', - 'debug_toolbar.panels.timer.TimerDebugPanel', - 'debug_toolbar.panels.settings_vars.SettingsVarsDebugPanel', - 'debug_toolbar.panels.headers.HeaderDebugPanel', - 'debug_toolbar.panels.request_vars.RequestVarsDebugPanel', - 'debug_toolbar.panels.template.TemplateDebugPanel', - 'debug_toolbar.panels.sql.SQLDebugPanel', - 'debug_toolbar.panels.signals.SignalDebugPanel', - 'debug_toolbar.panels.logger.LoggingPanel', -) diff --git a/template/allotter/apply.html b/template/allotter/apply.html deleted file mode 100644 index 201e1f2..0000000 --- a/template/allotter/apply.html +++ /dev/null @@ -1,109 +0,0 @@ -{% extends "base.html" %} - -{% load range_filter %} - -{% block title %} JAM 2012 Application form {% endblock %} - -{% block content %} - -

Welcome to JAM 2012 allotment!

- -

Read the following instructions carefully before continuing.

- -
-Choose the options as per your preference - -

You are eligible for {{first_paper}} - -{% comment %} -Checking if there is second paper and displaying its name. -{% endcomment %} - -{% if np == 2 %} - -and {{second_paper}} - -{% endif %} - -

- -

For the paper(s) in which you are in the merit list, the following -options are available to you. Please rank your choices.

- -

Preferences will be assigned to options in the ascending order. Make sure it's -None for all options after your last option(so that it is not considered).

- -
- -{% comment %} - -Listing the options for first test paper. -{% endcomment %} - -

Options available for {{first_paper}}

- -{% if error_message %}

{{ error_message }}

{% endif %} - -
-{% csrf_token %} - - - - - - - - - -{% for option in options_available_first %} - - - - - - -{% endfor %} -

Programme Code

Programme Name

Insitute

Preference

{{ option.opt_code }}

{{option.opt_name }}

{{option.opt_location }}

-
- -{% if np == 2 %} - -

Options available for {{second_paper}}

- - - - - - - - - -{% for option in options_available_second %} - - - - - - -{% endfor %} -

Programme Code

Programme Name

Insitute

Preference

{{option.opt_code }}

{{option.opt_name }}

{{option.opt_location }}

-
- -{% endif %} - -

-

- -
- -{% endblock content %} diff --git a/template/allotter/complete.html b/template/allotter/complete.html deleted file mode 100644 index 26ee46d..0000000 --- a/template/allotter/complete.html +++ /dev/null @@ -1,60 +0,0 @@ -{% extends "base.html" %} - -{% block title %}Options saved.{% endblock %} - -{% block content %} - -

The following options have been saved. Please verify them before logging out.

- -

Please keep in mind that, the next time you login you will be redirected to this page straightaway.

- -{% if options_chosen %} - - - - - - - - -{% for option in options_chosen %} - - - - - - -{% endfor %} - -

Programme Code

Programme Name

Insitute

Preference

{{ forloop.counter }}

{{ option.opt_code }}

{{ option.opt_name }}

{{ option.opt_location }}

- -{% if email %} - -An email with the list of options has been sent {{ email }} for book-keeping purposes. - -{% endif %} - -{% else %} - -

No Options were chosen, Press Edit Options to go back and select options otherwise Press logout to exit the allotment process

- -{% endif %} - -
-{% csrf_token %} - -
- -
-{% csrf_token %} - -
- -
-{% csrf_token %} - -
- -{% endblock content %} - - diff --git a/template/allotter/details.html b/template/allotter/details.html deleted file mode 100644 index 5beeb85..0000000 --- a/template/allotter/details.html +++ /dev/null @@ -1,19 +0,0 @@ -{% extends "base.html" %} - -{% block title %}Details form {% endblock %} - -{% block content %} -Please provide the following details. -
-{% csrf_token %} - - -{{ form.as_table }} -
- -

These details cannot be changed once entered.

- - -
- -{% endblock content %} diff --git a/template/allotter/hello.html b/template/allotter/hello.html deleted file mode 100644 index 0d07c7f..0000000 --- a/template/allotter/hello.html +++ /dev/null @@ -1,11 +0,0 @@ -{% extends "base.html" %} - -{% block title %} Welcome Note {% endblock %} - -{% block content %} -

Hello, there

- -

Welcome {{user.first_name.title}} {{user.last_name.title}}, -to JAM 2012 allotment!

- -{% endblock content %} diff --git a/template/allotter/login.html b/template/allotter/login.html deleted file mode 100644 index 72769a0..0000000 --- a/template/allotter/login.html +++ /dev/null @@ -1,21 +0,0 @@ -{% extends "base.html" %} - -{% block title %}Login{% endblock title %} - -{% block content %} -

Welcome to the Allotment. -Please login to proceed.

- -
-{% csrf_token %} - - -{{ form.as_table }} -
- -
- -
- - -{% endblock content %} diff --git a/template/allotter/register.html b/template/allotter/register.html deleted file mode 100644 index d7d04b9..0000000 --- a/template/allotter/register.html +++ /dev/null @@ -1,17 +0,0 @@ -{% extends "base.html" %} - -{% block title %}Registration form {% endblock %} - -{% block content %} -Please provide the following details. -
-{% csrf_token %} - - -{{ form.as_table }} -
- - -
- -{% endblock content %} diff --git a/template/base.html b/template/base.html deleted file mode 100644 index cd937ba..0000000 --- a/template/base.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - {% block title %} {% endblock %} - - - - - -
- {% block content %}{% endblock %} - {% block main_content %}{% endblock %} -
- - diff --git a/urls.py b/urls.py deleted file mode 100644 index f5fdfe0..0000000 --- a/urls.py +++ /dev/null @@ -1,18 +0,0 @@ -from django.conf.urls.defaults import patterns, include, url - -from django.contrib import admin - -admin.autodiscover() - -urlpatterns = patterns('', - url(r'^allotter/', include('allotter.urls')), - # Examples: - # url(r'^$', 'aloha.views.home', name='home'), - # url(r'^aloha/', include('aloha.foo.urls')), - - # Uncomment the admin/doc line below to enable admin documentation: - # url(r'^admin/doc/', include('django.contrib.admindocs.urls')), - - # Uncomment the next line to enable the admin: - url(r'^admin/', include(admin.site.urls)), -) -- cgit