diff options
-rw-r--r-- | allotter/forms.py | 28 | ||||
-rw-r--r-- | allotter/models.py | 8 | ||||
-rw-r--r-- | allotter/urls.py | 4 | ||||
-rw-r--r-- | allotter/views.py | 234 | ||||
-rw-r--r-- | template/allotter/apply.html | 21 | ||||
-rw-r--r-- | template/allotter/complete.html | 51 |
6 files changed, 238 insertions, 108 deletions
diff --git a/allotter/forms.py b/allotter/forms.py index 980d3f7..65e4cf6 100644 --- a/allotter/forms.py +++ b/allotter/forms.py @@ -80,3 +80,31 @@ class UserLoginForm(forms.Form): 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/models.py b/allotter/models.py index 25d3f44..9da8213 100644 --- a/allotter/models.py +++ b/allotter/models.py @@ -1,10 +1,6 @@ from django.db import models from django.contrib.auth.models import User -#email in profile -#course - place -#phone no(2) - ##EXAMINATION_SUBJECTS = ( ## ("Physics", "Physics"), ## ("Mathematics", "Mathematics"), @@ -79,7 +75,7 @@ class Option(models.Model): verbose_name_plural = "Options" def __unicode__(self): - return self.opt_name + return unicode(self.opt_code) class Application(models.Model): @@ -108,6 +104,8 @@ class Application(models.Model): 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 diff --git a/allotter/urls.py b/allotter/urls.py index 611fb88..09383e0 100644 --- a/allotter/urls.py +++ b/allotter/urls.py @@ -4,7 +4,9 @@ urlpatterns = patterns('allotter.views', url(r'^login/$', 'user_login'), url(r'^logout/$', 'user_logout'), url(r'^apply/$', 'apply'), - url(r'^(?P<reg_no>\w+)/submit/$', 'submit'), #change into numbers + url(r'^details/$', 'submit_details'), + url(r'^get_pdf/$', 'generate_pdf'), + url(r'^(?P<reg_no>\w+)/submit/$', 'submit_options'), #change into numbers url(r'^(?P<reg_no>\w+)/complete/$', 'complete'), #change into numbers url(r'^$', 'apply'), #url(r'^quit/$', 'quit'), diff --git a/allotter/views.py b/allotter/views.py index c9a5990..dcfd59f 100644 --- a/allotter/views.py +++ b/allotter/views.py @@ -11,7 +11,19 @@ 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 +from allotter.forms import UserLoginForm, UserDetailsForm + +from itertools import chain + +#Reportlab libraries +from django.http import HttpResponse +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): @@ -19,14 +31,22 @@ def user_login(request): user = request.user if user.is_authenticated(): - return redirect("/allotter/") + 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', args=(user.username,))) + else: #Otherwise to Option Choosing Page + return redirect("/allotter/details") if request.method == "POST": form = UserLoginForm(request.POST) if form.is_valid(): user = form.cleaned_data login(request, user) - return redirect("/allotter/") + status = user.get_profile().application.submitted #Getting the submission status + if status: + return HttpResponseRedirect(reverse('allotter.views.complete', args=(user.username,))) + else: + return redirect("/allotter/details") else: context = {"form": form} return render_to_response('allotter/login.html', context, @@ -38,26 +58,35 @@ def user_login(request): context_instance=RequestContext(request)) - -def get_options(user): - 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 - if(np == 2): - second_paper = user_application.second_paper - options_available_second = Option.objects.filter(exam__exam_name=second_paper).distinct() - - options_available = list(set(options_available_first + options_available_second)) +@login_required +def submit_details(request): + """ + Get the secondary email address, phone number and save it to the Profile. + """ + user = request.user - -## Retrieves the user details from the database and passes it for generation -## of Application Template - -##TODO: Display a single list of options for students who have taken two exams. - + 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_to_response('allotter/details.html', + {'form':form}, + context_instance=RequestContext(request)) + + else: + form = UserDetailsForm(request.user) + context = {"form": form} + return render_to_response('allotter/details.html', context, + context_instance=RequestContext(request)) + 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 @@ -72,18 +101,20 @@ def get_details(user, error_message = ""): 'options_available_first' : options_available_first, 'second_paper': second_paper, 'options_available_second' : options_available_second, - 'np' : np, 'oafl_range': range(1, oafl + 1, 1), - 'oasl_range': range(oafl, oafl + oasl, 1), + '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, - 'oafl_range': range(1, oafl + 1, 1), + 'options_range': range(1, oafl + 1, 1), 'np' : np, 'error_message' : error_message} return context @login_required def apply(request): + """ + Displays the application page for an authenticated user. + """ user = request.user if not(user.is_authenticated()): return redirect('/allotter/login/') @@ -102,78 +133,115 @@ def user_logout(request): #TODO: Extensive Testing -def submit(request, reg_no): +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 - options_list = "" - for option in options_available_first: - - #TODO: Dealing with none option, Dealing with all nones - option_pref = request.POST[option.opt_name] - #except (KeyError, Option.DoesNotExist): - # Redisplay the application form with error message. - # error_message = "You didn't select a choice." - # context = get_detail(user, error_message) - # return render_to_response('allotter/apply.html', context, - # context_instance=RequestContext(request)) - #else: + + 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_list += option_pref + "-" + str(option.opt_code) + "," - - user_application.options_selected += options_list + 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 #Setting the attribute in model + user_application.submitted = True #Submission Status user_application.save() return HttpResponseRedirect(reverse('allotter.views.complete', args=(reg_no,))) - #return redirect('/allotter/complete/') - -#User Application def complete(request, reg_no): user = get_object_or_404(User, username=reg_no) - email = user.email - user_profile = user.get_profile() - user_application = user_profile.application - 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 - context = {'user': reg_no, 'email': email, 'first_paper': first_paper, - 'options_available_first': options_available_first} + sec_email = user.get_profile().secondary_email + options_chosen = get_chosen_options(user) + context = {'user': reg_no, 'email': sec_email, + 'options_chosen': options_chosen} ci = RequestContext(request) return render_to_response('allotter/complete.html', context, context_instance=ci) - -"""def quit(request): - pass + + +def get_chosen_options(user): + 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 + +def generate_pdf(request, reg_no="1234567"): + 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 = '<font size=15>JAM 2012 Allotment.</font>' + elements.append(Paragraph(ptext, styles["Justify"])) + elements.append(Spacer(4, 20)) + + ptext = '<font size=12>Registration Number: %s</font>' % reg_no + elements.append(Paragraph(ptext, styles["Normal"])) + elements.append(Spacer(1, 12)) + + ptext = '<font size=12>Number of Papers Eligible: %s</font>' % np + elements.append(Paragraph(ptext, styles["Normal"])) + elements.append(Spacer(1, 12)) + + ptext = '<font size=12>Following are the options in order of preference</font>' + elements.append(Paragraph(ptext, styles["Normal"])) + elements.append(Spacer(1, 12)) + + data = [] + options = get_chosen_options(user) + counter = 1 + for opt in options: + data.append([counter, opt.opt_code, opt.opt_location, opt.opt_name]) + counter = counter + 1 -""" - -"""def user_register(request): - Register a new user. - Create a user and corresponding profile and store roll_number also. - - user = request.user - if user.is_authenticated(): - return redirect("/allotter/") - - if request.method == "POST": - form = RegistrationForm(request.POST) - if form.is_valid(): - data = form.cleaned_data - u_name, pwd = form.save_data() - - new_user = authenticate(username = u_name, password = pwd) - login(request, new_user) - return redirect("/allotter/") - - else: - return render_to_response('allotter/register.html', - {'form':form}, - context_instance=RequestContext(request)) - else: - form = RegistrationForm() - return render_to_response('allotter/register.html', - {'form':form}, - context_instance=RequestContext(request)) + 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 = '<font size=12>%s</font>' % formatted_time + elements.append(Paragraph(ptext, styles["Normal"])) + elements.append(Spacer(1, 12)) + + + doc.build(elements) + + return response + -""" diff --git a/template/allotter/apply.html b/template/allotter/apply.html index a336306..201e1f2 100644 --- a/template/allotter/apply.html +++ b/template/allotter/apply.html @@ -2,7 +2,7 @@ {% load range_filter %} -{% block title %} Application form {% endblock %} +{% block title %} JAM 2012 Application form {% endblock %} {% block content %} @@ -60,11 +60,11 @@ Listing the options for first test paper. <td><p> {{ option.opt_code }} </p></td> <td><p> {{option.opt_name }} </p></td> <td><p> {{option.opt_location }} </p></td> - <td><select name="{{option.opt_name}}"> - {% for i in oafl_range %} + <td><select name="{{option.opt_code}}"> + {% for i in options_range %} <option value="{{i}}" selected="selected">Preference {{i}}</option> {% endfor %} - <option value="{{option.opt_code}}">None</option> + <option value="0" selected="selected">None</option> </select> </td> </tr> @@ -88,11 +88,11 @@ Listing the options for first test paper. <td><p> {{option.opt_code }} </p></td> <td><p> {{option.opt_name }} </p></td> <td><p> {{option.opt_location }} </p></td> - <td><select name="{{option.opt_name}}"> - {% for i in oasl_range %} + <td><select name="{{option.opt_code}}"> + {% for i in options_range %} <option value="{{i}}" selected="selected">Preference {{i}}</option> {% endfor %} - <option value="{{option.opt_code}}">None</option> + <option value="0" selected="selected">None</option> </select> </td> </tr> @@ -101,12 +101,9 @@ Listing the options for first test paper. {% endif %} +<p><label for="check">I am responsible for my own choices.</label> +<input type="checkbox" name="check" id="check" /></p> <input type="submit" name="save" value="Save" /> </form> -<form action="/allotter/logout/" method="post"> -{% csrf_token %} -<input type="submit" name="logout" value="Quit Allotment" /> -</form> - {% endblock content %} diff --git a/template/allotter/complete.html b/template/allotter/complete.html index e235772..799d965 100644 --- a/template/allotter/complete.html +++ b/template/allotter/complete.html @@ -5,20 +5,57 @@ {% block content %} -<h2> Thank you, your following options have been saved to the database </h2> - -{{first_paper}} - -{% for option in options_available_first %} - <p>{{ option.opt_name }}</p> +<h2> The following options have been saved. Please verify them before logging out.</h2> + +<h3> Please keep in mind that, the next time you login you will be redirected to this page straightaway.</h3> + +{% if options_chosen %} +<table> +<tr> +<td><p>Programme Code </p></td> +<td><p>Programme Name </p></td> +<td><p>Insitute </p></td> +<td><p>Preference </p></td> +</tr> + +{% for option in options_chosen %} + <tr> + <td><p> {{ forloop.counter }} </p></td> + <td><p> {{ option.opt_code }} </p></td> + <td><p> {{ option.opt_name }} </p></td> + <td><p> {{ option.opt_location }} </p></td> + </tr> {% endfor %} +</table> + {% if email %} -An email with all the options has been to the following email address: {{email}} +An email with the list of options has been sent {{ email }} for book-keeping purposes. + +{% endif %} + +{% else %} + +<h3> No Options were chosen, Press Edit Options to go back and select options otherwise Press logout to exit the allotment process </h3> {% endif %} +<form action="/allotter/apply/" method="post"> +{% csrf_token %} +<input type="submit" name="apply" value="Edit Options" /> +</form> + +<form action="/allotter/get_pdf/" method="post"> +{% csrf_token %} +<input type="submit" name="get_pdf" value="Generate PDF" /> +</form> + +<form action="/allotter/logout/" method="post"> +{% csrf_token %} +<input type="submit" name="logout" value="Quit Allotment" /> +</form> + {% endblock content %} |