diff options
Diffstat (limited to 'project/scipycon')
42 files changed, 4055 insertions, 0 deletions
diff --git a/project/scipycon/__init__.py b/project/scipycon/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/project/scipycon/__init__.py diff --git a/project/scipycon/base/__init__.py b/project/scipycon/base/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/project/scipycon/base/__init__.py diff --git a/project/scipycon/base/admin.py b/project/scipycon/base/admin.py new file mode 100644 index 0000000..118808d --- /dev/null +++ b/project/scipycon/base/admin.py @@ -0,0 +1,45 @@ +from django.contrib import admin + +from project.scipycon.base.models import Event +from project.scipycon.base.models import Timeline + + +class EventAdmin(admin.ModelAdmin): + list_display = ('name', 'turn', 'status', 'scope') + list_filter = ('name', 'turn', 'status',) + search_fields = ('name', 'turn', 'status',) + fieldsets = ( + ('Details', { + 'fields': ('name', 'turn', 'status', 'scope') + }), + ) + + +class TimelineAdmin(admin.ModelAdmin): + list_display = ('registration_start', 'registration_end', 'cfp_start', + 'cfp_end', 'accepted_papers_announced', + 'proceedings_paper_deadline', 'event_start', + 'event_end', 'event') + list_filter = ('registration_start', 'registration_end', 'cfp_start', + 'cfp_end', 'accepted_papers_announced', + 'proceedings_paper_deadline', 'event_start', + 'event_end', 'event') + search_fields = ('registration_start', 'registration_end', 'cfp_start', + 'cfp_end', 'accepted_papers_announced', + 'proceedings_paper_deadline', 'event_start', + 'event_end') + fieldsets = ( + ('Registration', { + 'fields': ('registration_start', 'registration_end') + }), + ('Call for Papers', { + 'fields': ('cfp_start', 'cfp_end', 'accepted_papers_announced', + 'proceedings_paper_deadline') + }), + ('Event', { + 'fields': ('event_start', 'event_end', 'event') + }), + ) + +admin.site.register(Event, EventAdmin) +admin.site.register(Timeline, TimelineAdmin) diff --git a/project/scipycon/base/models.py b/project/scipycon/base/models.py new file mode 100644 index 0000000..3146ca4 --- /dev/null +++ b/project/scipycon/base/models.py @@ -0,0 +1,81 @@ +from django.db import models + + +class Event(models.Model): + """Data model which holds the data related to the scope or the event. + """ + + # Different states the Event can be in + STATUS_CHOICES = ( + ('active', 'Active'), + ('inactive', 'Inactive'), + ) + + # Scope of the program, used as a URL prefix + scope = models.CharField(max_length=255) + + # Name of the program + name = models.CharField(max_length=255) + + # Event specific i.e version of the event + turn = models.CharField(max_length=255) + + # Status of the program + status = models.CharField(max_length=255, choices=STATUS_CHOICES) + + def __unicode__(self): + return '%s %s' % (self.name, self.turn) + + def get_full_name(self): + return self.__unicode__() + + +class Timeline(models.Model): + """Timeline of the program + """ + + # Event with which this timeline is associated + event = models.OneToOneField(Event) + + # Start of registration for the program + registration_start = models.DateTimeField(blank=True, null=True) + + # End of registration for the program + registration_end = models.DateTimeField(blank=True, null=True) + + # Start of Call for Papers + cfp_start = models.DateTimeField(blank=True, null=True) + + # End of Call for Papers + cfp_end = models.DateTimeField(blank=True, null=True) + + # Accepted papers announced + accepted_papers_announced = models.DateTimeField(blank=True, null=True) + + # Deadline to submit proceedings paper + proceedings_paper_deadline = models.DateTimeField(blank=True, null=True) + + # Start of the actual program + event_start = models.DateTimeField(blank=True, null=True) + + # End of the actual program + event_end = models.DateTimeField(blank=True, null=True) + + def __unicode__(self): + return '%s %s' % (self.event.name, self.event.turn) + + +class ScopedBase(models.Model): + """Base model which is in turn inherited by other models + which needs to be scoped. + """ + + # Scope of entity in which it is visible + scope = models.ForeignKey(Event) + + class Meta: + abstract = True + + +class Paid(models.Model): + event_start = models.DateTimeField(blank=True, null=True) diff --git a/project/scipycon/proceedings/__init__.py b/project/scipycon/proceedings/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/project/scipycon/proceedings/__init__.py diff --git a/project/scipycon/proceedings/admin.py b/project/scipycon/proceedings/admin.py new file mode 100644 index 0000000..bf379f2 --- /dev/null +++ b/project/scipycon/proceedings/admin.py @@ -0,0 +1,16 @@ +from django.contrib import admin + +from project.scipycon.proceedings.models import Paper + + +class PaperAdmin(admin.ModelAdmin): + list_display = ('title', 'abstract') + list_filter = ('title', 'authors') + search_fields = ('title', 'abstract', 'authors') + fieldsets = ( + ('Details', { + 'fields': ('title', 'abstract', 'body', 'authors') + }), + ) + +admin.site.register(Paper, PaperAdmin) diff --git a/project/scipycon/proceedings/booklet/__init__.py b/project/scipycon/proceedings/booklet/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/project/scipycon/proceedings/booklet/__init__.py diff --git a/project/scipycon/proceedings/booklet/mk_booklet.py b/project/scipycon/proceedings/booklet/mk_booklet.py new file mode 100644 index 0000000..c27ddf7 --- /dev/null +++ b/project/scipycon/proceedings/booklet/mk_booklet.py @@ -0,0 +1,94 @@ +# encoding: utf-8 + +import os +import sys +import codecs +import re + +try: + from sanum import model +except: + root_dir = os.path.abspath(os.getcwd() + '/../../') + os.chdir(root_dir) + sys.path.append(root_dir) + from sanum import model + +import sanum + +import turbogears +turbogears.update_config(configfile="dev.cfg", + modulename="sanum.config") + + +from mk_scipy_paper import tex2pdf, current_dir , copy_files, preamble, \ + render_abstract, addfile, sourcedir, outdir, outfilename + + +def hack_include_graphics(latex_text, attach_dir): + """ Replaces all the \includegraphics call with call that impose the + width to be 0.9\linewidth. + """ + latex_text = re.sub(r'\\includegraphics(\[.*\])?\{', + r'\includegraphics\1{' + attach_dir, + latex_text) + return latex_text + + +class MyStringIO(object): + """ An unicode-friendly stringIO-like object. + """ + + def __init__(self): + self.lines = [] + + def write(self, line): + self.lines.append(line) + + def getvalue(self): + return u''.join(self.lines) + +def mk_booklet_tex(outfilename): + """ Generate the entire booklet latex file. + """ + outfile = codecs.open(outfilename, 'w', 'utf-8') + preamble(outfile) + copy_files() + #addfile(outfile, sourcedir + os.sep + 'title.tex') + addfile(outfile, sourcedir + os.sep + 'introduction.tex') + + #outfile.write(ur'\setcounter{page}{0}' + '\n') + + #from sanum.controllers import Root as Controller + abstracts = model.Abstract.select() + for abstract in abstracts: + if not abstract.approved: + continue + print abstract.title + # Hack: I don't use a stringIO, because it is not unicode-safe. + tmpout = MyStringIO() + # Hack: I don't wont to be bound to the controller, to be + # abstractle to run without cherrypy. + #attach_dir = Controller._paper_attach_dir(abstract.id) + attach_dir = os.path.abspath(os.sep.join( + (os.path.dirname(sanum.__file__), 'static', + 'papers', '%i' % abstract.id))) + os.sep + render_abstract(tmpout, abstract) + outstring = hack_include_graphics(tmpout.getvalue(), + attach_dir) + outfile.write(outstring) + #outfile.write(ur'\fillbreak' + '\n') + + outfile.write(ur'\end{document}' + '\n') + + + + +def mk_booklet(outfilename=outfilename): + """ Generate the entire booklet pdf file. + """ + name, ext = os.path.splitext(outfilename) + mk_booklet_tex(name + '.tex') + return tex2pdf(name, remove_tex=False, timeout=60) + +if __name__ == '__main__': + mk_booklet(outfilename) diff --git a/project/scipycon/proceedings/booklet/mk_scipy_paper.py b/project/scipycon/proceedings/booklet/mk_scipy_paper.py new file mode 100644 index 0000000..7b4eca0 --- /dev/null +++ b/project/scipycon/proceedings/booklet/mk_scipy_paper.py @@ -0,0 +1,463 @@ +# encoding: utf-8 + +import os +import re +import sys +import shutil +import codecs +from glob import glob + +from docutils import core as docCore + +conf_name = 'SciPy2009' + +current_dir = '/media/python/workspace/scipycon/project/scipycon/proceedings/booklet' + +outdir = current_dir + os.sep + 'output' + +sourcedir = current_dir + os.sep + 'sources' +try: + os.mkdir(outdir) +except: + pass + +outfilename = outdir + os.sep + 'booklet.tex' + +############################################################################## +# Routines for supervised execution +############################################################################## + +from threading import Thread +import os +import signal +from subprocess import Popen +from time import sleep + +def delayed_kill(pid, delay=10): + sleep(delay) + try: + os.kill(pid, signal.SIGTERM) + except OSError: + pass + +def supervise_popen(command, timeout=10): + process = Popen(command) + Thread(target=delayed_kill, args=(process.pid,timeout),).start() + + process.wait() + + + +############################################################################## +# LaTeX generation functions. +############################################################################## + +def protect(string): + r''' Protects all the "\" in a string by adding a second one before + + >>> protect(r'\foo \*') + '\\\\foo \\\\*' + ''' + return re.sub(r"\\", r"\\\\", string) + + +def safe_unlink(filename): + """ Remove a file from the disk only if it exists, if not r=fails silently + """ + if os.path.exists(filename): + os.unlink(filename) + +rxcountpages = re.compile(r"$\s*/Type\s*/Page[/\s]", re.MULTILINE|re.DOTALL) + +def count_pages(filename): + data = file(filename,"rb").read() + return len(rxcountpages.findall(data)) + + +def tex2pdf(filename, remove_tex=True, timeout=10, runs=2): + """ Compiles a TeX file with pdfLaTeX (or LaTeX, if or dvi ps requested) + and cleans up the mess afterwards + """ + current_dir = os.getcwd() + os.chdir(os.path.dirname(filename)) + print >> sys.stderr, "Compiling document to pdf" + basename = os.path.splitext(os.path.basename(filename))[0] + if os.path.exists(basename + '.pdf'): + os.unlink(basename + '.pdf') + for _ in range(runs): + supervise_popen(("pdflatex", "--interaction", "scrollmode", + os.path.basename(filename)), timeout=timeout) + error_file = None + errors = file(os.path.abspath(basename + '.log')).readlines()[-1] + if not os.path.exists(basename + '.pdf') or \ + "Fatal error" in errors: + error_file = os.path.abspath(basename + '.log') + if remove_tex: + safe_unlink(filename+".tex") + safe_unlink(filename+".log") + safe_unlink(filename+".aux") + safe_unlink(filename+".out") + os.chdir(current_dir) + return error_file + + +def rst2latex(rst_string, no_preamble=True, allow_latex=True): + """ Calls docutils' engine to convert a rst string to a LaTeX file. + """ + overrides = {'output_encoding': 'utf-8', 'initial_header_level': 3, + 'no_doc_title': True, 'use_latex_citations': True, + 'use_latex_footnotes':True} + if allow_latex: + rst_string = u'''.. role:: math(raw) + :format: latex + \n\n''' + rst_string + tex_string = docCore.publish_string( + source=rst_string, + writer_name='latex2e', + settings_overrides=overrides) + if no_preamble: + extract_document = \ + re.compile(r'.*\\begin\{document\}(.*)\\end\{document\}', + re.DOTALL) + matches = extract_document.match(tex_string) + tex_string = matches.groups()[0] + return tex_string + + +def get_latex_preamble(): + """ Retrieve the required preamble from docutils. + """ + full_document = rst2latex('\n', no_preamble=False) + preamble = re.split(r'\\begin\{document\}', full_document)[0] + ## Remove the documentclass. + preamble = r""" + %s + \makeatletter + \newcommand{\class@name}{gael} + \makeatother + \usepackage{ltxgrid} + %s + """ % ( + preamble.split('\n')[0], + '\n'.join(preamble.split('\n')[1:]), + ) + return preamble + + +############################################################################## +# Functions to generate part of the booklet +############################################################################## +def addfile(outfile, texfilename): + """ Includes the content of a tex file in our outfile. + """ + include = codecs.open(texfilename, 'r') + data = include.readlines() + outfile.write(ur'\thispagestyle{empty}' + u'\n') + outfile.writelines(data) + + +def preamble(outfile): + outfile.write(r''' + %s + \usepackage{abstracts} + \usepackage{ltxgrid} + \usepackage{amssymb,latexsym,amsmath,amsthm} + \usepackage{longtable} + \geometry{left=.8cm, textwidth=17cm, bindingoffset=0.6cm, + textheight=25.3cm, twoside} + \usepackage{hyperref} + \hypersetup{pdftitle={Proceedings of the 8th Annual Python in Science Conference}} + \begin{document} + + '''.encode('utf-8') % get_latex_preamble()) + + # XXX SciPy08 should not be hard coded, but to run out of the webapp + +def hack_include_graphics(latex_text): + """ Replaces all the \includegraphics call with call that impose the + width to be 0.9\linewidth. + """ + latex_text = re.sub(r'\\setlength\{\\rightmargin\}\{\\leftmargin\}', + r'\\setlength{\\leftmargin}{4ex}\\setlength{\\rightmargin}{0ex}', + latex_text) + latex_text = re.sub(r'\\begin\{quote\}\n\\begin\{itemize\}', + r'\\begin{itemize}', + latex_text) + latex_text = re.sub(r'\\end\{itemize\}\n\\end\{quote\}', + r'\\end{itemize}', + latex_text) + latex_text = re.sub(r'\\includegraphics(\[.*\])?\{', + r'\includegraphics[width=\linewidth]{', + latex_text) + latex_text = re.sub(r'\\href\{([^}]+)\}\{http://(([^{}]|(\{[^}]*\}))+)\}', + r'''% +% Break penalties to have URL break easily: +\mathchardef\UrlBreakPenalty=0 +\mathchardef\UrlBigBreakPenalty=0 +%\hskip 0pt plus 2em +\href{\1}{\url{\1}}''', + latex_text) + latex_text = re.sub(r'\\href\{([^}]+)\}\{https://(([^{}]|(\{[^}]*\}))+)\}', + r'''% +% Break penalties to have URL break easily: +\mathchardef\UrlBreakPenalty=0 +\mathchardef\UrlBigBreakPenalty=0 +\linebreak +\href{\1}{\url{\1}}''', + latex_text) + + return latex_text + + +def render_abstract(outfile, abstract, start_page=None): + """ Writes the LaTeX string corresponding to one abstract. + """ + if start_page is not None: + outfile.write(r""" +\setcounter{page}{%i} +""" % start_page) + else: + if hasattr(abstract, 'start_page'): + start_page = abstract.start_page + else: + start_page = 1 + if not abstract.authors: + author_list = abstract.owners + else: + author_list = abstract.authors + authors = [] + print dir(author_list[0]) + for author in author_list: + # If the author has no surname, he is not an author + if author.surname: + if author.email_address: + email = r'(\email{%s})' % author.email_address + else: + email = '' + authors.append(ur'''\otherauthors{ + %s %s + %s -- + \address{%s, %s} + }''' % (author.first_names, author.surname, + email, + author.institution, + author.city)) + if authors: + authors = u'\n'.join(authors) + authors += r'\addauthorstoc{%s}' % ', '.join( + '%s. %s' % (author.first_names[0], author.surname) + for author in author_list + ) + author_cite_list = ['%s. %s' % (a.first_names[0], a.surname) + for a in author_list] + if len(author_cite_list) > 4: + author_cite_list = author_cite_list[:3] + author_cite_list.append('et al.') + citation = ', '.join(author_cite_list) + \ + 'in Proc. SciPy 2009, G. Varoquaux, S. van der Walt, J. Millman (Eds), ' + copyright = '\\copyright 2009, %s' % ( ', '.join(author_cite_list)) + else: + authors = '' + citation = 'Citation' + copyright = 'Copyright' + if hasattr(abstract, 'num_pages'): + citation += 'pp. %i--%i' % (start_page, start_page + + abstract.num_pages) + else: + citation += 'p. %i'% start_page + if hasattr(abstract, 'number'): + abstract.url = 'http://conference.scipy.org/proceedings/%s/paper_%i' \ + % (conf_name, abstract.number) + url = r'\url{%s}' % abstract.url + else: + url = '' + paper_text = abstract.paper_text + if paper_text == '': + paper_text = abstract.summary + # XXX: It doesn't seem to be right to be doing this, but I get a + # nasty UnicodeDecodeError on some rare abstracts, elsewhere. + paper_text = codecs.utf_8_decode(hack_include_graphics( + rst2latex(paper_text)))[0] + paper_abstract = abstract.paper_abstract + if paper_abstract is None: + paper_abstract = '' + if not paper_abstract=='': + paper_abstract = ur'\begin{abstract}%s\end{abstract}' % \ + paper_abstract#.encode('utf-8') + abstract_dict = { + 'text': paper_text.encode('utf-8'), + 'abstract': paper_abstract.encode('utf-8'), + 'authors': authors.encode('utf-8'), + 'title': abstract.title.encode('utf-8'), + 'citation': citation.encode('utf-8'), + 'copyright': copyright.encode('utf-8'), + 'url': url.encode('utf-8'), + } + outfile.write(codecs.utf_8_decode(ur''' +\phantomsection +\hypertarget{chapter}{} +\vspace*{-2em} + +\resetheadings{%(title)s}{%(citation)s}{%(url)s}{%(copyright)s} +\title{%(title)s} + +\begin{minipage}{\linewidth} +%(authors)s +\end{minipage} + +\noindent\rule{\linewidth}{0.2ex} +\vspace*{-0.5ex} +\twocolumngrid +%(abstract)s + +\sloppy + +%(text)s + +\fussy +\onecolumngrid +\smallskip +\vfill +\filbreak +\clearpage + +'''.encode('utf-8') % abstract_dict )[0]) + +def copy_files(dest=outfilename): + """ Copy the required file from the source dir to the output dir. + """ + dirname = os.path.dirname(dest) + if dirname == '': + dirname = '.' + for filename in glob(sourcedir+os.sep+'*'): + destfile = os.path.abspath(dirname + os.sep + + os.path.basename(filename)) + shutil.copy2(filename, destfile) + + +def mk_abstract_preview(abstract, outfilename, attach_dir, start_page=None): + """ Generate a preview for an given paper. + """ + copy_files() + outdir = os.path.dirname(os.path.abspath(outfilename)) + for f in glob(os.path.join(attach_dir, '*')): + if os.path.isdir(f) and not os.path.exists(f): + os.makedirs(f) + else: + if not outdir == os.path.dirname(os.path.abspath(f)): + shutil.copy2(f, outdir) + for f in glob(os.path.join(sourcedir, '*')): + if os.path.isdir(f): + os.makedirs(f) + else: + destfile = os.path.abspath(os.path.join(outdir, f)) + shutil.copy2(f, outdir) + + outbasename = os.path.splitext(outfilename)[0] + outfilename = outbasename + '.tex' + + outfile = codecs.open(outfilename, 'w', 'utf-8') + preamble(outfile) + render_abstract(outfile, abstract, start_page=start_page) + outfile.write(ur'\end{document}' + u'\n') + outfile.close() + + tex2pdf(outbasename, remove_tex=False) + abstract.num_pages = count_pages(outbasename + '.pdf') + + # Generate the tex file again, now that we know the length. + outfile = codecs.open(outfilename, 'w', 'utf-8') + preamble(outfile) + render_abstract(outfile, abstract, start_page=start_page) + outfile.write(ur'\end{document}' + u'\n') + outfile.close() + + return tex2pdf(os.path.splitext(outfilename)[0], remove_tex=False) + + +############################################################################## +# Code for using outside of the webapp. +############################################################################## + +def mk_zipfile(): + """ Generates a zipfile with the required files to build an + abstract. + """ + from zipfile import ZipFile + zipfilename = os.path.join(os.path.dirname(__file__), + 'mk_scipy_paper.zip') + z = ZipFile(zipfilename, 'w') + for filename in glob(os.path.join(sourcedir, '*')): + if not os.path.isdir(filename): + z.write(filename, arcname='source/' + os.path.basename(filename)) + z.write(__file__, arcname='mk_scipy_paper.py') + return zipfilename + +class Bunch(dict): + def __init__(self, **kwargs): + dict.__init__(self, **kwargs) + self.__dict__ = self + + def __reprt(self): + return repr(self.__dict__) + +author_like = Bunch( + first_names='XX', + surname='XXX', + email_address='xxx@XXX', + institution='XXX', + address='XXX', + country='XXX' +) + + +abstract_like = Bunch( + paper_abstract='An abstract', + authors=[author_like, ], + title='', + ) + +if __name__ == '__main__': + from optparse import OptionParser + parser = OptionParser() + parser.add_option("-o", "--output", dest="outfilename", + default="./paper.pdf", + help="output to FILE", metavar="FILE") + parser.usage = """%prog [options] rst_file [data_file] + Compiles a given rest file and information file to pdf for the SciPy + proceedings. + """ + + (options, args) = parser.parse_args() + if not len(args) in (1, 2): + print "One or two arguments required: the input rest file and " \ + "the input data file" + print '' + parser.print_help() + sys.exit(1) + infile = args[0] + if len(args)==1: + data_file = 'data.py' + if os.path.exists('data.py'): + print "Using data file 'data.py'" + else: + print "Generating the data file and storing it in data.py" + print "You will need to edit this file to add title, author " \ + "information, and abstract." + abstract = abstract_like + file('data.py', 'w').write(repr(abstract)) + elif len(args)==2: + data_file = args[1] + + abstract = Bunch( **eval(file(data_file).read())) + abstract.authors = [Bunch(**a) for a in abstract.authors] + + abstract['summary'] = u'' + abstract['paper_text'] = file(infile).read().decode('utf-8') + + outfilename = options.outfilename + + mk_abstract_preview(abstract, options.outfilename, + os.path.dirname(options.outfilename)) + # Ugly, but I don't want to wait on the thread. + sys.exit() diff --git a/project/scipycon/proceedings/forms.py b/project/scipycon/proceedings/forms.py new file mode 100644 index 0000000..ddff13c --- /dev/null +++ b/project/scipycon/proceedings/forms.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- + +from django import forms + + +class ProceedingsForm(forms.Form): + """Form for proceedings. + """ + + title = forms.CharField(required=True, label=u'Title', + widget=forms.TextInput(attrs={'size':'70'})) + + abstract = forms.CharField( + widget=forms.Textarea(attrs={'cols': '80', 'rows': '8'}), + required=True, label=u'Abstract', + help_text=u'Upto 200 words. Content must strictly be in reSt format.') + + body = forms.CharField( + widget=forms.Textarea(attrs={'cols': '80', 'rows': '25'}), + required=False, label=u'Body', help_text=u'Approximately 7 pages. ' + 'Content must strictly be in reSt format.') + + rst_file = forms.FileField( + required=False, label=u'reStructuredText file', + help_text=u'The file should contain two sections, one with a heading ' + "'Abstract' and other with a heading 'Body'.") + + authors = forms.CharField( + required=False, label=u'Author(s)', + help_text=u'Comma separated list of User ID of the author(s).') diff --git a/project/scipycon/proceedings/models.py b/project/scipycon/proceedings/models.py new file mode 100644 index 0000000..171861f --- /dev/null +++ b/project/scipycon/proceedings/models.py @@ -0,0 +1,32 @@ +from django.db import models +from django.contrib.auth.models import User + +from project.scipycon.base import models as base_models + + +class Paper(base_models.ScopedBase): + """Data model for storing proceedings paper. + """ + + # Title of the paper + title = models.CharField(max_length=200) + + # Abstract to be published with the paper + abstract = models.TextField() + + # Body text of the paper + body = models.TextField() + + # Authors + authors = models.ManyToManyField(User) + + +class Attachments(models.Model): + """Stores attachments for papers. + """ + + # Attachment for generating paper + attachments = models.FileField(upload_to='attachments/%Y/%m/%d') + + # The paper to which this attachment belongs to + paper = models.ForeignKey(Paper) diff --git a/project/scipycon/proceedings/views.py b/project/scipycon/proceedings/views.py new file mode 100644 index 0000000..b86fb72 --- /dev/null +++ b/project/scipycon/proceedings/views.py @@ -0,0 +1,203 @@ +import os + +from django.contrib.auth import login +from django.contrib.auth.decorators import login_required +from django.contrib.auth.forms import AuthenticationForm +from django.contrib.auth.models import User +from django.core.urlresolvers import reverse +from django.shortcuts import render_to_response +from django.template import RequestContext + +from project.scipycon.proceedings.booklet import mk_scipy_paper +from project.scipycon.proceedings.forms import ProceedingsForm +from project.scipycon.proceedings.models import Paper +from project.scipycon.user.forms import RegisterForm +from project.scipycon.user.models import UserProfile +from project.scipycon.utils import set_message_cookie + + +def handleUploadedFile(proceedings_form_data, rst_file): + """Handles the uploaded file content and process the form + """ + + title = proceedings_form_data.get('title') + abstract = proceedings_form_data.get('abstract') + body = proceedings_form_data.get('body') + authors = proceedings_form_data.get('authors') + + if rst_file: + destination = open('some/file/name.txt', 'wb+') + for chunk in rst_file.chunks(): + destination.write(chunk) + destination.close() + + return title, abstract, body, authors + + +@login_required +def submit(request, scope, id=None, template='proceedings/submit.html'): + """View to submit the proceedings paper. + """ + + user = request.user + if user.is_authenticated(): + try: + profile = user.get_profile() + except: + profile, new = UserProfile.objects.get_or_create(user=user) + if new: + profile.save() + message = None + + if request.method == 'POST': + register_form = RegisterForm(data=request.POST) + + if request.POST.get('action', None) == 'login': + login_form = AuthenticationForm(data=request.POST) + if login_form.is_valid(): + + login(request, login_form.get_user()) + + redirect_to = reverse('scipycon_submit_proceedings', + kwargs={'scope': scope}) + return set_message_cookie(redirect_to, + msg = u'You have been logged in.') + + if request.POST.get('action', None) == 'register': + # add the new user + if register_form.is_valid(): + + user = scipycon_createuser(request, register_form.data) + + proceedings_form = ProceedingsForm(data=request.POST, + files=request.FILES) + + if proceedings_form.is_valid(): + if user.is_authenticated(): + # Data from reSt file is appended to the data in fields + title, abstract, body, authors = handleUploadedFile( + proceedings_form.cleaned_data, request.FILES.get('file')) + + paper = edit(id, title=title, + abstract=abstract, body=body, + authors=authors) if id else create(title=title, + abstract=abstract, body=body, + authors=authors) + + # Successfully saved. So get back to the edit page. + redirect_to = reverse('scipycon_submit_proceedings', + args=[paper.id], kwargs={'scope': scope}) + return set_message_cookie( + redirect_to, msg = u'Thanks, your paper has been submitted.') + else: + # This is impossible. Something was wrong so return back + # to submit page + redirect_to = reverse('scipycon_submit_proceedings', + kwargs={'scope': scope}) + return set_message_cookie( + redirect_to, msg = u'Something is wrong here.') + else: + if id: + # If id exists initialize the form with old values + paper = Paper.objects.get(id=id) + proceedings_form = ProceedingsForm( + initial={'title': paper.title, + 'abstract': paper.abstract, + 'body': paper.body, + 'authors': ', '.join([ + author.username for author in paper.authors.all()]) + }) + else: + # Otherwise create a new form + proceedings_form = ProceedingsForm() + + register_form = RegisterForm() + login_form = AuthenticationForm() + + context = RequestContext(request, { + 'proceedings_form': proceedings_form, + 'register_form' : register_form, + 'message' : message, + 'login_form' : login_form + }) + + context['id'] = id if id else None + + return render_to_response(template, context) + + +def create(**kwargs): + """View to create a new proceedings. + """ + + title = kwargs.get('title') + abstract = kwargs.get('abstract') + body = kwargs.get('body') + authors = kwargs.get('authors') + + paper = Paper(title=title, abstract=abstract, body=body) + paper.save() + + if authors: + authors = authors.split(',') + for author in authors: + user = User.objects.get(username=author.strip()) + paper.authors.add(user) + + return paper + + +def edit(id, **kwargs): + """View to edit the proceedings paper. + """ + + paper = Paper.objects.get(id=id) + + paper.title = kwargs.get('title') + paper.abstract = kwargs.get('abstract') + paper.body = kwargs.get('body') + authors = kwargs.get('authors') + + if authors: + authors = authors.split(',') + for author in authors: + user = User.objects.get(username=author.strip()) + paper.authors.add(user) + + paper.save() + + return paper + + +def show_paper(request, id): + """Display the thumbnail of the rendered paper for download + """ + + paper = Paper.objects.get(id=id) + + paper_data = { + 'paper_abstract': paper.abstract, + 'authors': [ + {'first_names': author.first_name, + 'surname': author.last_name, + 'address': 'XXX', + 'country': 'XXX', + 'email_address': 'XXX@xx.com', + 'institution': 'XXX' + } for author in paper.authors.all()], + 'title': paper.title + } + + abstract = mk_scipy_paper.Bunch(**paper_data) + abstract.authors = [mk_scipy_paper.Bunch(**a) for a in abstract.authors] + + abstract['paper_text'] = paper.body + + outfilename = '/media/python/workspace/scipycon/project/scipycon/proceedings/booklet/output/paper.pdf' + attach_dir = os.path.dirname('/media/python/workspace/scipycon/project/scipycon/proceedings/booklet/output/') + mk_scipy_paper.mk_abstract_preview(abstract, outfilename, attach_dir) + + from django.http import HttpResponse + + # TODO: Return something in the repo + return HttpResponse('') diff --git a/project/scipycon/registration/__init__.py b/project/scipycon/registration/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/project/scipycon/registration/__init__.py diff --git a/project/scipycon/registration/admin.py b/project/scipycon/registration/admin.py new file mode 100644 index 0000000..fc79f9b --- /dev/null +++ b/project/scipycon/registration/admin.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import + +#django.contrib +from django.contrib import admin + +#scipycon +from .models import Accommodation +from .models import Payment +from .models import Registration +from .models import Wifi + +class RegistrationAdmin(admin.ModelAdmin): + list_display = ('registrant', 'full_name', 'phone_num', + 'laptop', 'slug', 'email', 'city', + 'organisation', 'occupation', 'postcode', + 'tshirt', 'conference', 'tutorial', + 'sprint', 'allow_contact') + fieldsets = ( + ('Details', { + 'fields': ('slug', 'registrant', 'organisation', 'occupation', + 'city', 'tshirt') + }), + ('Information', { + 'fields': ('allow_contact',), + }), + ) + + search_fields = ['registrant__username', 'registrant__email'] + + def email(self, obj): + return obj.registrant.email + + def full_name(self, obj): + return obj.registrant.get_full_name() + + def laptop(self, obj): + return obj.registrant.wifi_set.values()[0]['wifi'] + +admin.site.register(Registration, RegistrationAdmin) + +class WifiAdmin(admin.ModelAdmin): + list_display = ('user', 'wifi',) + list_filter = ('wifi',) + +admin.site.register(Wifi, WifiAdmin) + +class AccommodationAdmin(admin.ModelAdmin): + list_display = ('user', 'sex', 'accommodation_required', + 'accommodation_days') + +admin.site.register(Accommodation, AccommodationAdmin) + +class PaymentAdmin(admin.ModelAdmin): + list_display = ('user', 'confirmed', 'acco_confirmed') + +admin.site.register(Payment, PaymentAdmin) + + diff --git a/project/scipycon/registration/forms.py b/project/scipycon/registration/forms.py new file mode 100644 index 0000000..77a8b73 --- /dev/null +++ b/project/scipycon/registration/forms.py @@ -0,0 +1,251 @@ +from django import forms +from django.core.exceptions import ObjectDoesNotExist + +from project.scipycon.registration.models import SIZE_CHOICES +from project.scipycon.registration.models import OCCUPATION_CHOICES +from project.scipycon.registration.models import Accommodation +from project.scipycon.registration.models import Payment +from project.scipycon.registration.models import Wifi + + +class RegistrationSubmitForm(forms.Form): + """SciPyCon registration form + """ + #tshirt = forms.ChoiceField(choices=SIZE_CHOICES, required=True, + # label=u'T-shirt size', help_text=u'Yes, we all get a t-shirt!') + organisation = forms.CharField(required=True, label=u'Organisation', + help_text=u'The primary organisation that you are a member of.', + max_length=255, + widget=forms.TextInput(attrs={'size':'50'})) + occupation = forms.ChoiceField(choices=OCCUPATION_CHOICES, + required=True, label=u'Occupation', + help_text=u'Title of your occupation') + city = forms.CharField(required=False, label=u'City', + help_text=u'Your city of residence', + max_length=255, + widget=forms.TextInput(attrs={'size':'50'})) + postcode = forms.CharField(required=False, label=u'Postcode', + help_text=u'PIN Code of your area', + max_length=10, + widget=forms.TextInput(attrs={'size':'10'})) + phone_num = forms.CharField(required=False, label=u'Phone Number', + help_text=u'Phone number. Although optional, please provide it for ' + 'faster correspondence', max_length=14, + widget=forms.TextInput(attrs={'size':'20'})) + allow_contact = forms.BooleanField(required=False, label=u'Contact', + help_text=u'May organizers of SciPy.in contact you after the event?') + conference = forms.BooleanField(required=False, label=u'Conference', + help_text=u"""Do you intend to attend SciPy.in 2011 conference?""") + tutorial = forms.BooleanField(required=False, label=u'Tutorial', + help_text=u'Do you intend to attend the tutorials?') + sprint = forms.BooleanField(required=False, label=u'Sprint', + help_text=u'Do you intend to attend the sprints?') + + def occupation_fields(self): + return (self['organisation'], + self['occupation']) + + def demographic_fields(self): + return (self['city'], + self['postcode'], + self['phone_num']) + + def personal_fields(self): + return (#self['tshirt'], + self['conference'], + self['tutorial'], + self['sprint'], + self['allow_contact']) + + +class RegistrationEditForm(RegistrationSubmitForm): + id = forms.CharField(widget=forms.HiddenInput) + +class WifiForm(forms.ModelForm): + """SciPyCon wifi form + """ + + def save(self, user, scope): + try: + wifi = Wifi.objects.get(user=user, scope=scope) + except ObjectDoesNotExist: + wifi = Wifi(user=user, scope=scope) + + wifi.wifi = self.cleaned_data['wifi'] + wifi.registration_id = self.cleaned_data['registration_id'] + wifi.save() + + return wifi + + class Meta: + model = Wifi + fields = ('wifi', 'registration_id') + + +class AccommodationForm(forms.ModelForm): + """SciPyCon Accommodation form + """ + + def save(self, user, scope): + try: + acco = Accommodation.objects.get(user=user, scope=scope) + except ObjectDoesNotExist: + acco = Accommodation(user=user, scope=scope) + + sex = self.cleaned_data['sex'] + accommodation_required = self.cleaned_data['accommodation_required'] + + a1 = self.cleaned_data['accommodation_on_1st'] + a2 = self.cleaned_data['accommodation_on_2nd'] + a3 = self.cleaned_data['accommodation_on_3rd'] + a4 = self.cleaned_data['accommodation_on_4th'] + + + accommodation_days = [a1, a2, a3, a4].count(True) + + acco.sex = sex + acco.accommodation_required = accommodation_required + acco.accommodation_days = accommodation_days + + acco.accommodation_on_1st = a1 + acco.accommodation_on_2nd = a2 + acco.accommodation_on_3rd = a3 + acco.accommodation_on_4th = a4 + + + acco.save() + + return acco + + def clean(self): + """Makes sure that accommodation form is correct, i.e. sex + and number of days required are filled in when the accommodation + is required. + """ + cleaned = self.cleaned_data + + sex = self.cleaned_data['sex'] + accommodation_required = self.cleaned_data['accommodation_required'] + + a1 = self.cleaned_data['accommodation_on_1st'] + a2 = self.cleaned_data['accommodation_on_2nd'] + a3 = self.cleaned_data['accommodation_on_3rd'] + a4 = self.cleaned_data['accommodation_on_4th'] + + selected_a_date = any([a1, a2, a3, a4]) + + if accommodation_required and (not sex or not selected_a_date): + #or accommodation_days == 0): + raise forms.ValidationError( + u"If accommodation is required please specify gender and" + " select the days number for which accommodation is required.") + + return super(AccommodationForm, self).clean() + + class Meta: + model = Accommodation + fields = ('accommodation_required', + 'sex', + 'accommodation_on_1st', + 'accommodation_on_2nd', + 'accommodation_on_3rd', + 'accommodation_on_4th', + ) + + +class PaymentForm(forms.ModelForm): + """SciPyCon Payment form + """ + + paid = forms.BooleanField( + required=False, label="Amount paid", + help_text="Check this box if you have already paid the fees.") + + def save(self, user, scope): + try: + payment = Payment.objects.get(user=user, scope=scope) + except ObjectDoesNotExist: + payment = Payment(user=user, scope=scope) + + paid = self.cleaned_data['paid'] + type = self.cleaned_data['type'] + details = self.cleaned_data['details'] + + payment.type = type + payment.details = details + + payment.save() + + return payment + + def clean(self): + """Makes sure that payment form is correct, i.e. type and details + are filled in when the required fees is paid. + """ + + paid = self.cleaned_data['paid'] + type = self.cleaned_data['type'] + details = self.cleaned_data['details'] + + if paid and (not type or not details): + raise forms.ValidationError( + u"If you have already paid the fee it is mandatory to " + "fill in the type and mandatory fields.") + + return super(PaymentForm, self).clean() + + class Meta: + model = Payment + fields = ('paid', 'type', 'details') + + +PC = ( + ('all', 'all'), + ('paid', 'paid'), + ('not paid', 'not paid') + ) +HC = ( + ('all', 'all'), + ('party', 'party'), + ('no party', 'no party') + ) +AC = ( + ('all', 'all'), + ('0', '0'), + ('10', '10'), + ('20', '20'), + ('40', '40'), + ) +OC = ( + ('email', 'email'), + ('amount', 'amount'), + ) + +IC = ( + ('Name', 'name'), + ('Email', 'email'), + ('Amount', 'amount'), + ('Organisation', 'organisation'), + ('Conference', 'conference'), + ('Tutorial', 'tutorial'), + ('Sprint', 'sprint'), + ('T-size', 'tshirt'), + ) + + +class RegistrationAdminSelectForm(forms.Form): + """ + Used to make selection for csv download + """ + by_payment = forms.ChoiceField(choices=PC, required=False, + label=u'By payment') + by_amount = forms.MultipleChoiceField(choices=AC, required=False, + label=u'By amount') + by_party = forms.ChoiceField(choices=HC, required=False, + label=u'by party') + by_tshirt = forms.ChoiceField(choices=SIZE_CHOICES, required=False, + label=u'by tshirt size') + order_by = forms.ChoiceField(choices=OC, required=False, + label=u'order results') + include = forms.MultipleChoiceField(choices=IC, required=False, + label=u'Include fields') diff --git a/project/scipycon/registration/labels.py b/project/scipycon/registration/labels.py new file mode 100644 index 0000000..c465f2c --- /dev/null +++ b/project/scipycon/registration/labels.py @@ -0,0 +1,7 @@ + +WIFI_CHOICES = ( + ("0", "Yes"), + ('1', 'No'), + ) + +WIFI_HELP = """Are you bringing a laptop to the event?""" diff --git a/project/scipycon/registration/migrations/0001_initial.py b/project/scipycon/registration/migrations/0001_initial.py new file mode 100644 index 0000000..9c1eb53 --- /dev/null +++ b/project/scipycon/registration/migrations/0001_initial.py @@ -0,0 +1,192 @@ + +from south.db import db +from django.db import models +from project.scipycon.registration.models import * + +class Migration: + + def forwards(self, orm): + + # Adding model 'Wifi' + db.create_table('registration_wifi', ( + ('id', orm['registration.Wifi:id']), + ('scope', orm['registration.Wifi:scope']), + ('user', orm['registration.Wifi:user']), + ('wifi', orm['registration.Wifi:wifi']), + ('registration_id', orm['registration.Wifi:registration_id']), + )) + db.send_create_signal('registration', ['Wifi']) + + # Adding model 'Accommodation' + db.create_table('registration_accommodation', ( + ('id', orm['registration.Accommodation:id']), + ('scope', orm['registration.Accommodation:scope']), + ('user', orm['registration.Accommodation:user']), + ('sex', orm['registration.Accommodation:sex']), + ('accommodation_required', orm['registration.Accommodation:accommodation_required']), + ('accommodation_on_1st', orm['registration.Accommodation:accommodation_on_1st']), + ('accommodation_on_2nd', orm['registration.Accommodation:accommodation_on_2nd']), + ('accommodation_on_3rd', orm['registration.Accommodation:accommodation_on_3rd']), + ('accommodation_on_4th', orm['registration.Accommodation:accommodation_on_4th']), + ('accommodation_on_5th', orm['registration.Accommodation:accommodation_on_5th']), + ('accommodation_on_6th', orm['registration.Accommodation:accommodation_on_6th']), + ('accommodation_days', orm['registration.Accommodation:accommodation_days']), + )) + db.send_create_signal('registration', ['Accommodation']) + + # Adding model 'Payment' + db.create_table('registration_payment', ( + ('id', orm['registration.Payment:id']), + ('scope', orm['registration.Payment:scope']), + ('user', orm['registration.Payment:user']), + ('confirmed', orm['registration.Payment:confirmed']), + ('acco_confirmed', orm['registration.Payment:acco_confirmed']), + ('date_confirmed', orm['registration.Payment:date_confirmed']), + ('confirmed_mail', orm['registration.Payment:confirmed_mail']), + ('acco_confirmed_mail', orm['registration.Payment:acco_confirmed_mail']), + ('type', orm['registration.Payment:type']), + ('details', orm['registration.Payment:details']), + )) + db.send_create_signal('registration', ['Payment']) + + # Adding model 'Registration' + db.create_table('registration_registration', ( + ('id', orm['registration.Registration:id']), + ('scope', orm['registration.Registration:scope']), + ('slug', orm['registration.Registration:slug']), + ('registrant', orm['registration.Registration:registrant']), + ('organisation', orm['registration.Registration:organisation']), + ('occupation', orm['registration.Registration:occupation']), + ('city', orm['registration.Registration:city']), + ('postcode', orm['registration.Registration:postcode']), + ('phone_num', orm['registration.Registration:phone_num']), + ('tshirt', orm['registration.Registration:tshirt']), + ('conference', orm['registration.Registration:conference']), + ('tutorial', orm['registration.Registration:tutorial']), + ('sprint', orm['registration.Registration:sprint']), + ('final_conference', orm['registration.Registration:final_conference']), + ('final_tutorial', orm['registration.Registration:final_tutorial']), + ('final_sprint', orm['registration.Registration:final_sprint']), + ('allow_contact', orm['registration.Registration:allow_contact']), + ('submitted', orm['registration.Registration:submitted']), + ('last_mod', orm['registration.Registration:last_mod']), + )) + db.send_create_signal('registration', ['Registration']) + + + + def backwards(self, orm): + + # Deleting model 'Wifi' + db.delete_table('registration_wifi') + + # Deleting model 'Accommodation' + db.delete_table('registration_accommodation') + + # Deleting model 'Payment' + db.delete_table('registration_payment') + + # Deleting model 'Registration' + db.delete_table('registration_registration') + + + + models = { + 'auth.group': { + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'unique_together': "(('content_type', 'codename'),)"}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'base.event': { + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'scope': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'status': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'turn': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'unique_together': "(('app_label', 'model'),)", 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'registration.accommodation': { + 'accommodation_days': ('django.db.models.fields.IntegerField', [], {'default': '0', 'blank': 'True'}), + 'accommodation_on_1st': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'accommodation_on_2nd': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'accommodation_on_3rd': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'accommodation_on_4th': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'accommodation_on_5th': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'accommodation_on_6th': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'accommodation_required': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'scope': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['base.Event']"}), + 'sex': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'registration.payment': { + 'acco_confirmed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'acco_confirmed_mail': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'confirmed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'confirmed_mail': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'date_confirmed': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'details': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'scope': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['base.Event']"}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '25', 'null': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'registration.registration': { + 'allow_contact': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'city': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'conference': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'final_conference': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'final_sprint': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'final_tutorial': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_mod': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'occupation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'organisation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'phone_num': ('django.db.models.fields.CharField', [], {'max_length': '14', 'blank': 'True'}), + 'postcode': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'registrant': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), + 'scope': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['base.Event']"}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}), + 'sprint': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'submitted': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'tshirt': ('django.db.models.fields.CharField', [], {'max_length': '3'}), + 'tutorial': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}) + }, + 'registration.wifi': { + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'registration_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'scope': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['base.Event']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), + 'wifi': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + } + } + + complete_apps = ['registration'] diff --git a/project/scipycon/registration/migrations/0002_auto__add_field_payment_acco_confirmed.py b/project/scipycon/registration/migrations/0002_auto__add_field_payment_acco_confirmed.py new file mode 100644 index 0000000..13bb22f --- /dev/null +++ b/project/scipycon/registration/migrations/0002_auto__add_field_payment_acco_confirmed.py @@ -0,0 +1,117 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + +class Migration(SchemaMigration): + + def forwards(self, orm): + + # Adding field 'Payment.acco_confirmed' + db.add_column('registration_payment', 'acco_confirmed', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False) + + + def backwards(self, orm): + + # Deleting field 'Payment.acco_confirmed' + db.delete_column('registration_payment', 'acco_confirmed') + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'base.event': { + 'Meta': {'object_name': 'Event'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'scope': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'status': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'turn': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'registration.accommodation': { + 'Meta': {'object_name': 'Accommodation'}, + 'accommodation_days': ('django.db.models.fields.IntegerField', [], {'default': '0', 'blank': 'True'}), + 'accommodation_required': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'scope': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['base.Event']"}), + 'sex': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'registration.payment': { + 'Meta': {'object_name': 'Payment'}, + 'acco_confirmed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'confirmed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'details': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'scope': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['base.Event']"}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '25', 'null': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'registration.registration': { + 'Meta': {'object_name': 'Registration'}, + 'allow_contact': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'city': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'conference': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'final_conference': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'final_sprint': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'final_tutorial': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_mod': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'occupation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'organisation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'phone_num': ('django.db.models.fields.CharField', [], {'max_length': '14', 'blank': 'True'}), + 'postcode': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'registrant': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), + 'scope': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['base.Event']"}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}), + 'sprint': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'submitted': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'tshirt': ('django.db.models.fields.CharField', [], {'max_length': '3'}), + 'tutorial': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'registration.wifi': { + 'Meta': {'object_name': 'Wifi'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'registration_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'scope': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['base.Event']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), + 'wifi': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + } + } + + complete_apps = ['registration'] diff --git a/project/scipycon/registration/migrations/0003_auto__add_field_payment_date_confirmed.py b/project/scipycon/registration/migrations/0003_auto__add_field_payment_date_confirmed.py new file mode 100644 index 0000000..052a1ac --- /dev/null +++ b/project/scipycon/registration/migrations/0003_auto__add_field_payment_date_confirmed.py @@ -0,0 +1,118 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + +class Migration(SchemaMigration): + + def forwards(self, orm): + + # Adding field 'Payment.date_confirmed' + db.add_column('registration_payment', 'date_confirmed', self.gf('django.db.models.fields.DateTimeField')(default=False, blank=True), keep_default=False) + + + def backwards(self, orm): + + # Deleting field 'Payment.date_confirmed' + db.delete_column('registration_payment', 'date_confirmed') + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'base.event': { + 'Meta': {'object_name': 'Event'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'scope': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'status': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'turn': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'registration.accommodation': { + 'Meta': {'object_name': 'Accommodation'}, + 'accommodation_days': ('django.db.models.fields.IntegerField', [], {'default': '0', 'blank': 'True'}), + 'accommodation_required': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'scope': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['base.Event']"}), + 'sex': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'registration.payment': { + 'Meta': {'object_name': 'Payment'}, + 'acco_confirmed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'confirmed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'date_confirmed': ('django.db.models.fields.DateTimeField', [], {'default': 'False', 'blank': 'True'}), + 'details': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'scope': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['base.Event']"}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '25', 'null': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'registration.registration': { + 'Meta': {'object_name': 'Registration'}, + 'allow_contact': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'city': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'conference': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'final_conference': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'final_sprint': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'final_tutorial': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_mod': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'occupation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'organisation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'phone_num': ('django.db.models.fields.CharField', [], {'max_length': '14', 'blank': 'True'}), + 'postcode': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'registrant': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), + 'scope': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['base.Event']"}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}), + 'sprint': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'submitted': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'tshirt': ('django.db.models.fields.CharField', [], {'max_length': '3'}), + 'tutorial': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'registration.wifi': { + 'Meta': {'object_name': 'Wifi'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'registration_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'scope': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['base.Event']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), + 'wifi': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + } + } + + complete_apps = ['registration'] diff --git a/project/scipycon/registration/migrations/0004_auto__chg_field_payment_date_confirmed.py b/project/scipycon/registration/migrations/0004_auto__chg_field_payment_date_confirmed.py new file mode 100644 index 0000000..6ef942b --- /dev/null +++ b/project/scipycon/registration/migrations/0004_auto__chg_field_payment_date_confirmed.py @@ -0,0 +1,118 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + +class Migration(SchemaMigration): + + def forwards(self, orm): + + # Changing field 'Payment.date_confirmed' + db.alter_column('registration_payment', 'date_confirmed', self.gf('django.db.models.fields.DateTimeField')(null=True)) + + + def backwards(self, orm): + + # Changing field 'Payment.date_confirmed' + db.alter_column('registration_payment', 'date_confirmed', self.gf('django.db.models.fields.DateTimeField')()) + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'base.event': { + 'Meta': {'object_name': 'Event'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'scope': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'status': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'turn': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'registration.accommodation': { + 'Meta': {'object_name': 'Accommodation'}, + 'accommodation_days': ('django.db.models.fields.IntegerField', [], {'default': '0', 'blank': 'True'}), + 'accommodation_required': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'scope': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['base.Event']"}), + 'sex': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'registration.payment': { + 'Meta': {'object_name': 'Payment'}, + 'acco_confirmed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'confirmed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'date_confirmed': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'details': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'scope': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['base.Event']"}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '25', 'null': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'registration.registration': { + 'Meta': {'object_name': 'Registration'}, + 'allow_contact': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'city': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'conference': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'final_conference': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'final_sprint': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'final_tutorial': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_mod': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'occupation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'organisation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'phone_num': ('django.db.models.fields.CharField', [], {'max_length': '14', 'blank': 'True'}), + 'postcode': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'registrant': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), + 'scope': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['base.Event']"}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}), + 'sprint': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'submitted': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'tshirt': ('django.db.models.fields.CharField', [], {'max_length': '3'}), + 'tutorial': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'registration.wifi': { + 'Meta': {'object_name': 'Wifi'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'registration_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'scope': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['base.Event']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), + 'wifi': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + } + } + + complete_apps = ['registration'] diff --git a/project/scipycon/registration/migrations/0005_auto__add_field_payment_confirmed_mail__add_field_payment_acco_confirm.py b/project/scipycon/registration/migrations/0005_auto__add_field_payment_confirmed_mail__add_field_payment_acco_confirm.py new file mode 100644 index 0000000..d7aee62 --- /dev/null +++ b/project/scipycon/registration/migrations/0005_auto__add_field_payment_confirmed_mail__add_field_payment_acco_confirm.py @@ -0,0 +1,126 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + +class Migration(SchemaMigration): + + def forwards(self, orm): + + # Adding field 'Payment.confirmed_mail' + db.add_column('registration_payment', 'confirmed_mail', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False) + + # Adding field 'Payment.acco_confirmed_mail' + db.add_column('registration_payment', 'acco_confirmed_mail', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False) + + + def backwards(self, orm): + + # Deleting field 'Payment.confirmed_mail' + db.delete_column('registration_payment', 'confirmed_mail') + + # Deleting field 'Payment.acco_confirmed_mail' + db.delete_column('registration_payment', 'acco_confirmed_mail') + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'base.event': { + 'Meta': {'object_name': 'Event'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'scope': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'status': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'turn': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'registration.accommodation': { + 'Meta': {'object_name': 'Accommodation'}, + 'accommodation_days': ('django.db.models.fields.IntegerField', [], {'default': '0', 'blank': 'True'}), + 'accommodation_required': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'scope': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['base.Event']"}), + 'sex': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'registration.payment': { + 'Meta': {'object_name': 'Payment'}, + 'acco_confirmed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'acco_confirmed_mail': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'confirmed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'confirmed_mail': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'date_confirmed': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'details': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'scope': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['base.Event']"}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '25', 'null': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'registration.registration': { + 'Meta': {'object_name': 'Registration'}, + 'allow_contact': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'city': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'conference': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'final_conference': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'final_sprint': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'final_tutorial': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_mod': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'occupation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'organisation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'phone_num': ('django.db.models.fields.CharField', [], {'max_length': '14', 'blank': 'True'}), + 'postcode': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'registrant': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), + 'scope': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['base.Event']"}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}), + 'sprint': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'submitted': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'tshirt': ('django.db.models.fields.CharField', [], {'max_length': '3'}), + 'tutorial': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'registration.wifi': { + 'Meta': {'object_name': 'Wifi'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'registration_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'scope': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['base.Event']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), + 'wifi': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + } + } + + complete_apps = ['registration'] diff --git a/project/scipycon/registration/migrations/0006_auto__add_field_accommodation_accommodation_on_1st__add_field_accommod.py b/project/scipycon/registration/migrations/0006_auto__add_field_accommodation_accommodation_on_1st__add_field_accommod.py new file mode 100644 index 0000000..60df42a --- /dev/null +++ b/project/scipycon/registration/migrations/0006_auto__add_field_accommodation_accommodation_on_1st__add_field_accommod.py @@ -0,0 +1,156 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + +class Migration(SchemaMigration): + + def forwards(self, orm): + + # Adding field 'Accommodation.accommodation_on_1st' + db.add_column('registration_accommodation', 'accommodation_on_1st', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False) + + # Adding field 'Accommodation.accommodation_on_2nd' + db.add_column('registration_accommodation', 'accommodation_on_2nd', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False) + + # Adding field 'Accommodation.accommodation_on_3rd' + db.add_column('registration_accommodation', 'accommodation_on_3rd', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False) + + # Adding field 'Accommodation.accommodation_on_4th' + db.add_column('registration_accommodation', 'accommodation_on_4th', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False) + + # Adding field 'Accommodation.accommodation_on_5th' + db.add_column('registration_accommodation', 'accommodation_on_5th', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False) + + # Adding field 'Accommodation.accommodation_on_6th' + db.add_column('registration_accommodation', 'accommodation_on_6th', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False) + + + def backwards(self, orm): + + # Deleting field 'Accommodation.accommodation_on_1st' + db.delete_column('registration_accommodation', 'accommodation_on_1st') + + # Deleting field 'Accommodation.accommodation_on_2nd' + db.delete_column('registration_accommodation', 'accommodation_on_2nd') + + # Deleting field 'Accommodation.accommodation_on_3rd' + db.delete_column('registration_accommodation', 'accommodation_on_3rd') + + # Deleting field 'Accommodation.accommodation_on_4th' + db.delete_column('registration_accommodation', 'accommodation_on_4th') + + # Deleting field 'Accommodation.accommodation_on_5th' + db.delete_column('registration_accommodation', 'accommodation_on_5th') + + # Deleting field 'Accommodation.accommodation_on_6th' + db.delete_column('registration_accommodation', 'accommodation_on_6th') + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'base.event': { + 'Meta': {'object_name': 'Event'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'scope': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'status': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'turn': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'registration.accommodation': { + 'Meta': {'object_name': 'Accommodation'}, + 'accommodation_days': ('django.db.models.fields.IntegerField', [], {'default': '0', 'blank': 'True'}), + 'accommodation_on_1st': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'accommodation_on_2nd': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'accommodation_on_3rd': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'accommodation_on_4th': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'accommodation_on_5th': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'accommodation_on_6th': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'accommodation_required': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'scope': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['base.Event']"}), + 'sex': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'registration.payment': { + 'Meta': {'object_name': 'Payment'}, + 'acco_confirmed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'acco_confirmed_mail': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'confirmed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'confirmed_mail': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'date_confirmed': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'details': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'scope': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['base.Event']"}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '25', 'null': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'registration.registration': { + 'Meta': {'object_name': 'Registration'}, + 'allow_contact': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'city': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'conference': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'final_conference': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'final_sprint': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'final_tutorial': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_mod': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'occupation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'organisation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'phone_num': ('django.db.models.fields.CharField', [], {'max_length': '14', 'blank': 'True'}), + 'postcode': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'registrant': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), + 'scope': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['base.Event']"}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}), + 'sprint': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'submitted': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'tshirt': ('django.db.models.fields.CharField', [], {'max_length': '3'}), + 'tutorial': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'registration.wifi': { + 'Meta': {'object_name': 'Wifi'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'registration_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'scope': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['base.Event']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), + 'wifi': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + } + } + + complete_apps = ['registration'] diff --git a/project/scipycon/registration/migrations/__init__.py b/project/scipycon/registration/migrations/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/project/scipycon/registration/migrations/__init__.py diff --git a/project/scipycon/registration/models.py b/project/scipycon/registration/models.py new file mode 100644 index 0000000..03013c5 --- /dev/null +++ b/project/scipycon/registration/models.py @@ -0,0 +1,167 @@ +from django.db import models +from django.contrib.auth.models import User + +from project.scipycon.base import models as base_models + +from project.scipycon.registration.labels import WIFI_CHOICES +from project.scipycon.registration.labels import WIFI_HELP + + +SIZE_CHOICES = ( + ('S', 'S'), + ('M', 'M'), + ('L', 'L'), + ('XL', 'XL'), + ('XXL', 'XXL'), + ) + +OCCUPATION_CHOICES = ( + ('Education: Student', 'Education: Student'), + ('Education: Faculty', 'Education: Faculty'), + ('Education: Research', 'Education: Research'), + ('Education: Other', 'Education: Other'), + ('Corporate: Research', 'Corporate: Research'), + ('Corporate: Other', 'Corporate: Other'), + ('Other', 'Other') + ) + +SEX_CHOICES = ( + ('Male', 'Male'), + ('Female', 'Female'), + ) + +PAYMENT_MODE_CHOICES = ( + ('Cheque', 'Cheque'), + ('Demand Draft(DD)', 'Demand Draft(DD)'), + ('Net Banking', 'Net Banking') + ) + + +class Wifi(base_models.ScopedBase): + """Defines wifi options at SciPy.in + """ + + user = models.ForeignKey(User) + + wifi = models.CharField(max_length=50, choices=WIFI_CHOICES, + help_text=WIFI_HELP, verbose_name="Laptop") + + registration_id = models.CharField( + max_length=255, verbose_name="Identification Number", + help_text="- Provide the serial or identification number at the " + "back of your laptop using which your laptop can be uniquely " + "identified. Ex: 8BDB8FB (Service Tag on Dell Laptops).<br /> - " + "This is for security reasons and will be used while you enter and " + "leave the venue.<br /> - Please don't provide the model number " + "like Dell Inspiron 1545. There may be many laptops of that model " + "and hence your laptop cannot be uniquely identified.", + blank=True, null=True) + + +class Accommodation(base_models.ScopedBase): + """Defines accommodation information for SciPy.in + """ + + user = models.ForeignKey(User) + + sex = models.CharField(max_length=50, choices=SEX_CHOICES, + verbose_name="Gender", + blank=True, null=True) + + accommodation_required = models.BooleanField( + default=False, blank=True, + verbose_name="Accommodation required", + help_text="Check if you need accommodation.") + + accommodation_on_1st = models.BooleanField( + default=False, verbose_name="Required for Ist Night") + accommodation_on_2nd = models.BooleanField( + default=False, verbose_name="Required for 2nd Night") + accommodation_on_3rd = models.BooleanField( + default=False, verbose_name="Required for 3rd Night") + accommodation_on_4th = models.BooleanField( + default=False, verbose_name="Required for 4th Night") + + accommodation_days = models.IntegerField( + default=0, blank=True, + verbose_name="Number of days", + help_text="Number of days the accommodation is required for?") + + +class Registration(base_models.ScopedBase): + """Defines registration at SciPy.in""" + + slug = models.SlugField() + + registrant = models.ForeignKey(User) + + organisation = models.CharField(max_length=255, blank=True) + + occupation = models.CharField(max_length=255, + choices=OCCUPATION_CHOICES, blank=True) + + city = models.CharField(max_length=255, blank=True) + + postcode = models.CharField(max_length=255, blank=True) + + phone_num = models.CharField(max_length=14, blank=True) + + tshirt = models.CharField(max_length=3, choices=SIZE_CHOICES) + + conference = models.BooleanField(default=False) + + tutorial = models.BooleanField(default=False) + + sprint = models.BooleanField(default=False) + + final_conference = models.BooleanField(default=False) + + final_tutorial = models.BooleanField(default=False) + + final_sprint = models.BooleanField(default=False) + + allow_contact = models.BooleanField(default=False) + + submitted = models.DateTimeField(auto_now_add=True) + + last_mod = models.DateTimeField(auto_now=True) + + def __unicode__(self): + return 'Registration for user: <%s %s> %s' % ( + self.registrant.first_name, + self.registrant.last_name, self.registrant.email) + + +class Payment(base_models.ScopedBase): + """Defines payment information for SciPy.in registrants + """ + + user = models.ForeignKey(User) + + confirmed = models.BooleanField( + default=False, blank=True) + + acco_confirmed = models.BooleanField( + default=False, blank=True) + + date_confirmed = models.DateTimeField(blank=True, null=True) + + confirmed_mail = models.BooleanField( + default=False, blank=True) + + acco_confirmed_mail = models.BooleanField( + default=False, blank=True) + + type = models.CharField(max_length=25, choices=PAYMENT_MODE_CHOICES, + verbose_name="Type", blank=True, null=True) + + details = models.CharField( + max_length=255, verbose_name="Details", + help_text="If the payment mode was cheque or DD please provide " + "the <font color='red'>cheque or DD number and the name of the bank " + "and branch</font>. Example: 4536234, SBI, IIT Powai, Mumbai.<br/> " + "If the payment mode was Net Banking please provide the <font " + "color='red'>last four digits of the account number and the name " + "of the account holder and the bank name</font> from which the " + "transfer was made. Example: 8804, Harish Chandra, SBI", + blank=True, null=True) diff --git a/project/scipycon/registration/tests.py b/project/scipycon/registration/tests.py new file mode 100644 index 0000000..0ea28b2 --- /dev/null +++ b/project/scipycon/registration/tests.py @@ -0,0 +1,19 @@ + + +def test_save_to_pdf(): + """ + >>> from .pdf import save_invoice + >>> from django.db.models.loading import get_model + >>> userModel = get_model('auth', 'user') + >>> user = userModel(username='joe', email='joe@gmail.com', + ... first_name='Joe', last_name='Bloggs') + >>> user.save() + >>> regModel = get_model('registration', 'registration') + >>> registration = regModel(registrant=user, amount=40, + ... slug='NZPYCON-0001') + >>> registration.save() + + >>> save_invoice(user, registration, 'registration/invoice.html') + + """ + pass diff --git a/project/scipycon/registration/utils.py b/project/scipycon/registration/utils.py new file mode 100644 index 0000000..bf4e0cd --- /dev/null +++ b/project/scipycon/registration/utils.py @@ -0,0 +1,38 @@ +from django.core.mail import EmailMessage + + +def send_confirmation(registrant, event ,password=None): + + message = EmailMessage() + message.subject = u'Registration to %s' % (event.get_full_name()) + message.from_email = u'admin@scipy.in' + message.to = [registrant.email] + + details = {'name': registrant.get_full_name(), + 'username': registrant.username, + 'password': password, + 'event_name': event.get_full_name(), + 'event_scope': event.scope, + } + + confirmation_newuser = """Dear %(name)s, + +Thank you, for registering for %(event_name)s! + +You may log in to the %(event_name)s website at +http://scipy.in/%(event_scope)s/login using the username - +%(username)s and the password - %(password)s. + +Looking forward to meet you at %(event_name)s. + +Regards, +SciPy.in Team + +If you lose your password, visit: http://scipy.in/password-reset +""" + + message.body = confirmation_newuser %(details) + + message.send() + + diff --git a/project/scipycon/registration/views.py b/project/scipycon/registration/views.py new file mode 100644 index 0000000..75f0562 --- /dev/null +++ b/project/scipycon/registration/views.py @@ -0,0 +1,583 @@ +import csv +import datetime +import time + +from django.contrib.auth import authenticate +from django.contrib.auth import login +from django.contrib.auth.decorators import login_required +from django.contrib.auth.forms import AuthenticationForm +from django.contrib.auth.models import User +from django.core.exceptions import ObjectDoesNotExist +from django.core.urlresolvers import reverse +from django.http import HttpResponse +from django.http import HttpResponseRedirect +from django.shortcuts import render_to_response +from django.template import loader +from django.template import RequestContext + +from project.scipycon.base.models import Event +from project.scipycon.registration.forms import RegistrationEditForm +from project.scipycon.registration.forms import RegistrationSubmitForm +from project.scipycon.registration.forms import AccommodationForm +from project.scipycon.registration.forms import PaymentForm +from project.scipycon.registration.forms import WifiForm +from project.scipycon.registration.models import Accommodation +from project.scipycon.registration.models import Payment +from project.scipycon.registration.models import Registration +from project.scipycon.registration.models import Wifi +from project.scipycon.registration.utils import send_confirmation +from project.scipycon.user.forms import RegistrantForm +from project.scipycon.user.models import UserProfile +from project.scipycon.user.utils import scipycon_createregistrant +from project.scipycon.utils import set_message_cookie + + +REG_TOTAL = 1000 + + +@login_required +def registrations(request, scope, + template_name='registration/registrations.html'): + """Simple page to count registrations""" + + registrations = Registration.objects.all().count() + + user = request.user + if user.is_authenticated(): + registration = Registration.objects.get(registrant=user) + else: + registration = None + + event = Event.objects.get(scope=scope) + + return render_to_response(template_name, RequestContext(request, { + 'params': {'scope': scope}, + 'over_reg' : registrations >= REG_TOTAL and True or False, + 'registrations' : registrations, + 'registration': registration, + 'event': event})) + +@login_required +def edit_registration(request, scope, id, + template_name='registration/edit-registration.html'): + """Allows users that submitted a registration to edit it. + """ + + scope_entity = Event.objects.get(scope=scope) + + reg = Registration.objects.get(pk=int(id)) + wifi = Wifi.objects.get(user=reg.registrant) + + # TODO: This is an ugly hack to add accommodation and payment forms + # details at later stage for SciPy.in 2010. This must be removed for + # SciPy.in 2011 + acco, acco_created = Accommodation.objects.get_or_create( + user=reg.registrant, scope=scope_entity) + payment, payment_created = Payment.objects.get_or_create( + user=reg.registrant, scope=scope_entity) + + if reg.registrant != request.user: + redirect_to = reverse('scipycon_account', kwargs={'scope': scope}) + + return set_message_cookie( + redirect_to, + msg = u'Redirected because the registration you selected' \ + + ' is not your own.') + + if request.method == 'POST': + registration_form = RegistrationEditForm(data=request.POST) + wifi_form = WifiForm(data=request.POST) + acco_form = AccommodationForm(data=request.POST) + payment_form = PaymentForm(data=request.POST) + + if (registration_form.is_valid() and wifi_form.is_valid() and + acco_form.is_valid() and payment_form.is_valid()): + reg.organisation = registration_form.data.get('organisation') + reg.occupation = registration_form.data.get('occupation') + reg.city = registration_form.data.get('city') + reg.phone_num = registration_form.data.get('phone_num') + reg.postcode = registration_form.data.get('postcode') + #reg.tshirt = registration_form.data.get('tshirt') + reg.allow_contact = registration_form.data.get( + 'allow_contact') and True or False + reg.conference = registration_form.data.get( + 'conference') and True or False + reg.tutorial = registration_form.data.get( + 'tutorial') and True or False + reg.sprint = registration_form.data.get( + 'sprint') and True or False + reg.save() + + wifi = wifi_form.save(reg.registrant, reg.scope) + acco = acco_form.save(reg.registrant, reg.scope) + payment = payment_form.save(reg.registrant, reg.scope) + + # Saved.. redirect + redirect_to = reverse('scipycon_account', kwargs={'scope': scope}) + + return set_message_cookie(redirect_to, + msg = u'Your changes have been saved.') + else: + registration_form = RegistrationEditForm(initial={ + 'id' : id, + 'organisation' : reg.organisation, + 'occupation' : reg.occupation, + 'city' : reg.city, + 'phone_num': reg.phone_num, + #'tshirt' : reg.tshirt, + 'conference': reg.conference, + 'tutorial': reg.tutorial, + 'postcode' : reg.postcode, + 'sprint' : reg.sprint, + 'allow_contact' : reg.allow_contact, + }) + wifi_form = WifiForm(initial={ + 'user': wifi.user, + 'scope': wifi.scope, + 'wifi': wifi.wifi, + 'registration_id': wifi.registration_id + }) + acco_form = AccommodationForm(initial={ + 'user': acco.user, + 'scope': acco.scope, + 'sex': acco.sex, + 'accommodation_required': acco.accommodation_required, + 'accommodation_on_1st': acco.accommodation_on_1st, + 'accommodation_on_2nd': acco.accommodation_on_2nd, + 'accommodation_on_3rd': acco.accommodation_on_3rd, + 'accommodation_on_4th': acco.accommodation_on_4th, + 'accommodation_on_5th': acco.accommodation_on_5th, + 'accommodation_on_6th': acco.accommodation_on_6th, + }) + payment_form = PaymentForm(initial={ + 'user': payment.user, + 'scope': payment.scope, + 'paid': payment.type or payment.details, + 'type': payment.type, + 'details': payment.details, + }) + + return render_to_response( + template_name, RequestContext(request, { + 'params': {'scope': scope}, + 'registration': {'id': id}, + 'registration_form': registration_form, + 'wifi_form': wifi_form, + 'acco_form': acco_form, + 'payment_form': payment_form})) + +def submit_registration(request, scope, + template_name='registration/submit-registration.html'): + """Allows user to edit registration + """ + + user = request.user + reg_count = Registration.objects.all().count() + + scope_entity = Event.objects.get(scope=scope) + + if user.is_authenticated(): + try: + profile = user.get_profile() + except: + profile, new = UserProfile.objects.get_or_create( + user=user, scope=scope_entity) + if new: + profile.save() + try: + registration = Registration.objects.get(registrant=user) + if registration: + redirect_to = reverse('scipycon_account', + kwargs={'scope': scope}) + return set_message_cookie( + redirect_to, msg = u'You have already been registered.') + + except ObjectDoesNotExist: + pass + + message = None + + if request.method == 'POST': + registration_form = RegistrationSubmitForm(data=request.POST) + registrant_form = RegistrantForm(data=request.POST) + wifi_form = WifiForm(data=request.POST) + acco_form = AccommodationForm(data=request.POST) + payment_form = PaymentForm(data=request.POST) + + if request.POST.get('action', None) == 'login': + login_form = AuthenticationForm(data=request.POST) + if login_form.is_valid(): + + login(request, login_form.get_user()) + + redirect_to = reverse('scipycon_submit_registration', + kwargs={'scope': scope}) + return set_message_cookie(redirect_to, + msg = u'You have been logged in please continue' + \ + 'with registration.') + + newuser = None + passwd = None + if not user.is_authenticated(): + if registrant_form.is_valid(): + newuser = scipycon_createregistrant( + request, registrant_form.data, scope) + + # Log in user + passwd = User.objects.make_random_password() + newuser.set_password(passwd) + newuser.save() + + user = authenticate(username=newuser.username, password=passwd) + + login(request, user) + + newuser = user + + else: + newuser = user + + if (registration_form.is_valid() and newuser and wifi_form.is_valid() + and acco_form.is_valid() and payment_form.is_valid()): + allow_contact = registration_form.cleaned_data.get( + 'allow_contact') and True or False + conference = registration_form.cleaned_data.get( + 'conference') and True or False + tutorial = registration_form.cleaned_data.get('tutorial') and \ + True or False + sprint = registration_form.cleaned_data.get('sprint') and \ + True or False + + registrant = User.objects.get(pk=newuser.id) + + reg = Registration( + scope=scope_entity, + registrant = registrant, + organisation = registration_form.cleaned_data.get( + 'organisation'), + occupation = registration_form.cleaned_data.get('occupation'), + city = registration_form.cleaned_data.get('city'), + #tshirt = registration_form.data.get('tshirt'), + postcode = registration_form.cleaned_data.get('postcode'), + phone_num = registration_form.cleaned_data.get('phone_num'), + allow_contact = allow_contact, + conference = conference, + tutorial = tutorial, + sprint = sprint) + reg.save() + + # get id and use as slug and invoice number + id = reg.id + slug = 'SCIPYIN2010%04d' % id + reg.slug = slug + reg.save() + + wifi = wifi_form.save(registrant, scope_entity) + acco = acco_form.save(registrant, scope_entity) + payment = payment_form.save(registrant, scope_entity) + + send_confirmation(registrant, scope_entity, password=passwd) + + redirect_to = reverse('scipycon_registrations', + kwargs={'scope': scope}) + return set_message_cookie(redirect_to, + msg = u'Thank you, your registration has been submitted '\ + 'and an email has been sent with payment details.') + + else: + registration_form = RegistrationSubmitForm() + registrant_form = RegistrantForm() + wifi_form = WifiForm() + acco_form = AccommodationForm() + payment_form = PaymentForm() + + login_form = AuthenticationForm() + + + return render_to_response(template_name, RequestContext(request, { + 'params': {'scope': scope}, + 'registration_form': registration_form, + 'registrant_form' : registrant_form, + 'over_reg' : reg_count >= REG_TOTAL and True or False, + 'acco_form': acco_form, + 'payment_form': payment_form, + 'wifi_form' : wifi_form, + 'message' : message, + 'login_form' : login_form + })) + + +@login_required +def regstats(request, scope, + template_name='registration/regstats.html'): + """View that gives the statistics of registrants. + """ + + if not request.user.is_staff: + redirect_to = reverse('scipycon_login', kwargs={'scope': scope}) + return set_message_cookie( + redirect_to, msg = u'You must be a staff on this website to ' + 'access this page.') + + reg_q = Registration.objects.all() + conf_num = reg_q.filter(conference=True).count() + tut_num = reg_q.filter(tutorial=True).count() + sprint_num = reg_q.filter(sprint=True).count() + + acco_q = Accommodation.objects.all() + male = acco_q.filter(sex='Male').count() + female = acco_q.filter(sex='Female').count() + + # Day 1 details + day1 = acco_q.filter(accommodation_on_1st=True) + acco_1 = { + 'total': day1.count(), + 'male': day1.filter(sex='Male').count(), + 'female': day1.filter(sex='Female').count() + } + + # Day 2 details + day2 = acco_q.filter(accommodation_on_2nd=True) + acco_2 = { + 'total': day2.count(), + 'male': day2.filter(sex='Male').count(), + 'female': day2.filter(sex='Female').count() + } + + # Day 3 details + day3 = acco_q.filter(accommodation_on_3rd=True) + acco_3 = { + 'total': day3.count(), + 'male': day3.filter(sex='Male').count(), + 'female': day3.filter(sex='Female').count() + } + + # Day 4 details + day4 = acco_q.filter(accommodation_on_4th=True) + acco_4 = { + 'total': day4.count(), + 'male': day4.filter(sex='Male').count(), + 'female': day4.filter(sex='Female').count() + } + + + # Day 5 details + day5 = acco_q.filter(accommodation_on_5th=True) + acco_5 = { + 'total': day5.count(), + 'male': day5.filter(sex='Male').count(), + 'female': day5.filter(sex='Female').count() + } + + # Day 6 details + day6 = acco_q.filter(accommodation_on_6th=True) + acco_6 = { + 'total': day6.count(), + 'male': day6.filter(sex='Male').count(), + 'female': day6.filter(sex='Female').count() + } + + return render_to_response(template_name, RequestContext(request, + {'params': {'scope': scope}, + 'conf_num': conf_num, + 'tut_num': tut_num, + 'sprint_num': sprint_num, + 'male': male, + 'female':female, + 'acco_days': [acco_1, acco_2, acco_3, acco_4, acco_5, acco_6], + })) + +@login_required +def regstats_download(request, scope): + """Sends a downloadable PDF for registration statistics + """ + + if not request.user.is_staff: + redirect_to = reverse('scipycon_login') + return HttpResponseRedirect(redirect_to) + + filename = 'regstats%s.csv' % datetime.datetime.strftime( + datetime.datetime.now(), '%Y%m%d%H%M%S') + + response = HttpResponse(mimetype='text/csv') + response['Content-Disposition'] = 'attachment; filename=%s' % ( + filename) + + output = csv.writer(response) + + output.writerow(['Name', 'Gender', 'City', + 'Registration Fees Paid', + 'Attending Conference', + 'Attending Tutorial', + 'Attending Sprint', + 'Laptop Identification Number', + 'Accommodation Fees Paid', + 'Accommodation on 12th night', + 'Accommodation on 13th night', + 'Accommodation on 14th night', + 'Accommodation on 15th night', + 'Accommodation on 16th night', + 'Accommodation on 17th night']) + + regs = Registration.objects.order_by( + 'registrant__first_name', 'registrant__last_name') + for reg in regs: + row = [] + + payment, create = reg.registrant.payment_set.get_or_create( + user=reg.registrant, scope=reg.scope) + acco, created = reg.registrant.accommodation_set.get_or_create( + user=reg.registrant, scope=reg.scope) + wifi, create = reg.registrant.wifi_set.get_or_create( + user=reg.registrant, scope=reg.scope) + + row.append('"%s"' % reg.registrant.get_full_name()) + row.append(acco.sex) + row.append(reg.city) + row.append('Yes' if payment.confirmed else 'No') + row.append('Yes' if reg.conference else 'No') + row.append('Yes' if reg.tutorial else 'No') + row.append('Yes' if reg.sprint else 'No') + row.append(wifi.registration_id) + row.append('Yes' if payment.acco_confirmed + else 'No') + row.append('Yes' if acco.accommodation_on_1st else 'No') + row.append('Yes' if acco.accommodation_on_2nd else 'No') + row.append('Yes' if acco.accommodation_on_3rd else 'No') + row.append('Yes' if acco.accommodation_on_4th else 'No') + row.append('Yes' if acco.accommodation_on_5th else 'No') + row.append('Yes' if acco.accommodation_on_6th else 'No') + output.writerow(row) + + #output.writerow() + return response + + +@login_required +def manage_payments(request, scope, + template_name='registration/manage_payments.html'): + """View that gives a form to manage payments. + """ + + if not request.user.is_superuser: + redirect_to = reverse('scipycon_login', kwargs={'scope': scope}) + return set_message_cookie( + redirect_to, msg = u'You must be an admin on this website to ' + 'access this page.') + + message = None + + scope_entity = Event.objects.get(scope=scope) + + if request.method == 'POST': + post_data = request.POST + list_user_ids = [] + + mail_subject = 'SciPy.in 2010: Confirmation of fee payment' + mail_template = 'notifications/payment_confirmation2010.html' + + def parse_form(): + """Helper function that gets the User ID from the + form name + """ + + confirmed_ids = [] + acco_ids = [] + date_ids = {} + + for name_string in post_data: + id_str_list = name_string.split('_') + if (len(id_str_list) == 3 and id_str_list[1] == 'id'): + if id_str_list[0] == 'confirmed': + confirmed_ids.append(int(id_str_list[2])) + if id_str_list[0] == 'acco': + acco_ids.append(int(id_str_list[2])) + if id_str_list[0] == 'date': + date_str = post_data.get(name_string, None) + if date_str: + date_ids[int(id_str_list[2])] = post_data.get( + name_string, '') + + return confirmed_ids, acco_ids, date_ids + + confirmed_ids, acco_ids, date_ids = parse_form() + + confirmed_users = set(User.objects.filter(id__in=confirmed_ids)) + acco_users = set(User.objects.filter(id__in=acco_ids)) + + # Users for whom both registration and accommodation is confirmed + for user in confirmed_users & acco_users: + payment, created = user.payment_set.get_or_create( + user=user, scope=scope_entity) + + payment.confirmed = True + payment.acco_confirmed = True + payment.save() + + if not payment.confirmed_mail and not payment.acco_confirmed_mail: + mail_message = loader.render_to_string( + mail_template, + dictionary={'name': user.get_full_name(), + 'acco': True, + 'reg': True}) + user.email_user(mail_subject, mail_message, + from_email='admin@scipy.in') + payment.confirmed_mail =True + payment.acco_confirmed_mail = True + payment.save() + + # Users for whom only registration is confirmed + for user in confirmed_users - acco_users: + payment, created = user.payment_set.get_or_create( + user=user, scope=scope_entity) + + payment.confirmed = True + payment.save() + + if not payment.confirmed_mail: + mail_message = loader.render_to_string( + mail_template, + dictionary={'name': user.get_full_name(), + 'reg': True}) + user.email_user(mail_subject, mail_message, + from_email='admin@scipy.in') + payment.confirmed_mail =True + payment.save() + + # Users for whom only accommodation is confirmed + for user in acco_users - confirmed_users: + payment, created = user.payment_set.get_or_create( + user=user, scope=scope_entity) + + payment.acco_confirmed = True + payment.save() + + if not payment.acco_confirmed_mail: + mail_message = loader.render_to_string( + mail_template, + dictionary={'name': user.get_full_name(), + 'acco': True}) + user.email_user(mail_subject, mail_message, + from_email='admin@scipy.in') + payment.acco_confirmed_mail = True + payment.save() + + # Users for whom fee payment date is updated + for id in date_ids: + user = User.objects.get(id=id) + payment, created = user.payment_set.get_or_create( + user=user, scope=scope_entity) + + time_format = "%m/%d/%Y" + date = datetime.datetime.fromtimestamp(time.mktime( + time.strptime(date_ids[id], time_format))) + + payment.date_confirmed = date + payment.save() + + registrants = Registration.objects.all() + + return render_to_response(template_name, RequestContext(request, + {'params': {'scope': scope}, + 'registrants': registrants, + })) diff --git a/project/scipycon/talk/__init__.py b/project/scipycon/talk/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/project/scipycon/talk/__init__.py diff --git a/project/scipycon/talk/admin.py b/project/scipycon/talk/admin.py new file mode 100644 index 0000000..db8fe3e --- /dev/null +++ b/project/scipycon/talk/admin.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import + +#django.contrib +from django.contrib import admin + +#scipycon +from .models import Talk + +class TalkAdmin(admin.ModelAdmin): + list_display = ('title', 'speaker', 'topic', 'duration', 'audience', 'approved', 'submitted') + list_filter = ('approved', 'submitted', 'audience', 'topic', 'speaker') + search_fields = ('slug', 'title', 'abstract') + prepopulate_from = {'slug': ('title',)} + fieldsets = ( + ('Details', { + 'fields': ('slug', 'title', 'abstract', 'speaker') + }), + ('Information', { + 'fields': ('topic', 'duration', 'audience', 'approved') + }), + ) +admin.site.register(Talk, TalkAdmin) diff --git a/project/scipycon/talk/forms.py b/project/scipycon/talk/forms.py new file mode 100644 index 0000000..72ec853 --- /dev/null +++ b/project/scipycon/talk/forms.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import + +#django +from django import forms + +#django.contrib +from django.contrib.auth.models import User + +#tagging +from tagging.forms import TagField + +#scipycon +#from .models import TOPIC_CHOICES +from .models import DURATION_CHOICES +from .models import AUDIENCE_CHOICES + + +class TalkSubmitForm(forms.Form): + """Submit talk form + """ + authors_bio = forms.CharField(widget=forms.Textarea, required=True, + label=u'Author(s) and short bio', + help_text=u'(include a bit about your qualifications regarding your presentation topic)') + contact = forms.EmailField(required=True, label=u'E-Mail ID', + help_text=u'Provide your email ID', + max_length=1024, + widget=forms.TextInput(attrs={'size':'50'})) + title = forms.CharField(required=True, label=u'Talk title', + help_text=u'Title of proposed presentation', + max_length=1024, + widget=forms.TextInput(attrs={'size':'50'})) + abstract = forms.CharField(widget=forms.Textarea, required=True, + help_text=u'Summary of proposed presentation (In 300-700 words)') +# outline = forms.CharField(widget=forms.Textarea, required=True, +# help_text=u'Outline of proposed presentation (around 200 words)') +# topic = forms.ChoiceField(choices=TOPIC_CHOICES, +# label=u'Topic', help_text=u'Select one of the available options or enter other topic') +# topic_other = forms.CharField(label=u'Other topic', +# help_text=u'Description of your topic', +# max_length=255, +# required=False, +# widget=forms.TextInput(attrs={'size':'50'})) + topic = forms.CharField(label=u'Topic', + help_text=u'Description of your topic or comma separated tags', + max_length=255, + required=False, + widget=forms.TextInput(attrs={'size':'50'})) + duration = forms.ChoiceField(choices=DURATION_CHOICES, required=True, + label=u'Preferred time slot', help_text=u'Select preferred time slot') + audience = forms.ChoiceField(choices=AUDIENCE_CHOICES, label=u'Intended audience', + help_text=u'Select one of the available options or enter other type of intended audience') +# audience_other = forms.CharField(label=u'Other intended audience', +# help_text=u'Description of intended audience (ie. Discordians)', +# max_length=128, +# required=False, +# widget=forms.TextInput(attrs={'size':'50'})) +# tags = TagField(max_length=255, +# widget=forms.TextInput(attrs={'size':'50'})) + +class TalkEditForm(TalkSubmitForm): + id = forms.CharField(widget=forms.HiddenInput) diff --git a/project/scipycon/talk/models.py b/project/scipycon/talk/models.py new file mode 100644 index 0000000..82c8f25 --- /dev/null +++ b/project/scipycon/talk/models.py @@ -0,0 +1,57 @@ +from django.db import models +from django.contrib.auth.models import User + +from tagging import register +from tagging.fields import TagField +from tagging.utils import parse_tag_input + +from project.scipycon.base import models as base_models + + +DURATION_CHOICES = ( + ('10', 'Lightning Talk (10 mins)'), + ('20', 'Short Talk (20 mins)'), + ('30', 'Standard Talk (30 mins)'), + ) + +AUDIENCE_CHOICES = ( + ('nonprogrammers', 'Non Programmer'), + ('beginers', 'Beginner Programmer'), + ('intermediate', 'Intermediate Programmer'), + ('advanced', 'Advanced Programmer'), + ) + + +class Talk(base_models.ScopedBase): + """Defines talks at SciPy.in + """ + + slug = models.SlugField() + + speaker = models.ForeignKey(User) + + authors_bio = models.TextField() + + contact = models.EmailField() + + title = models.CharField(max_length=1024) + + abstract = models.TextField() + + topic = models.CharField(max_length=255, blank=True) + + duration = models.CharField(max_length=3, choices=DURATION_CHOICES) + + audience = models.CharField(max_length=32, choices=AUDIENCE_CHOICES, blank=True) + + approved = models.BooleanField(default=False) + + submitted = models.DateTimeField(auto_now_add=True) + + last_mod = models.DateTimeField(auto_now=True) + + def __unicode__(self): + return self.title + + def get_tag_list(self): + return parse_tag_input(self.tags) diff --git a/project/scipycon/talk/templatetags/__init__.py b/project/scipycon/talk/templatetags/__init__.py new file mode 100644 index 0000000..792d600 --- /dev/null +++ b/project/scipycon/talk/templatetags/__init__.py @@ -0,0 +1 @@ +# diff --git a/project/scipycon/talk/templatetags/talk_extras.py b/project/scipycon/talk/templatetags/talk_extras.py new file mode 100644 index 0000000..e28f2bf --- /dev/null +++ b/project/scipycon/talk/templatetags/talk_extras.py @@ -0,0 +1,8 @@ +from django import template + +register = template.Library() + +def choice(choices, value): + return choices[value] + +register.filter('choice', choice) diff --git a/project/scipycon/talk/views.py b/project/scipycon/talk/views.py new file mode 100644 index 0000000..62ae38d --- /dev/null +++ b/project/scipycon/talk/views.py @@ -0,0 +1,225 @@ +from django.core.urlresolvers import reverse +from django.contrib.auth.decorators import login_required +from django.contrib.auth.forms import AuthenticationForm +from django.contrib.auth.models import User +from django.shortcuts import render_to_response +from django.template import RequestContext +from django.views.generic.list_detail import object_list +from django.views.generic.list_detail import object_detail + +from PIL import Image + +from tagging.models import Tag + +from project.scipycon.base.models import Event +from project.scipycon.talk.models import Talk +from project.scipycon.talk.forms import TalkSubmitForm +from project.scipycon.talk.forms import TalkEditForm +from project.scipycon.talk.models import DURATION_CHOICES +from project.scipycon.talk.models import AUDIENCE_CHOICES +from project.scipycon.utils import set_message_cookie +from project.scipycon.utils import slugify +from project.scipycon.user.models import UserProfile +from project.scipycon.user.forms import RegisterForm +from project.scipycon.user.utils import scipycon_createuser + + +@login_required +def list_my_talks(request, scope, template_name='talk/list-talks.html'): + """Lists all the talks for the user. + """ + + scope_entity = Event.objects.get(scope=scope) + + user = request.user + if user.is_authenticated(): + try: + profile = user.get_profile() + except: + profile, new = UserProfile.objects.get_or_create( + user=user, scope=scope_entity) + if new: + profile.save() + + my_talks = user.talk_set.all() + + return render_to_response(template_name, RequestContext(request, { + 'params': {'scope': scope}, + 'talk_list': my_talks, + })) + +def talk(request, scope, id): + objects = Talk.objects.filter(approved=True) + audience = {} + for choice in AUDIENCE_CHOICES: + audience[choice[0]] = choice[1] + extra_context = dict(choices=audience) + return object_detail(request, objects, id, extra_context=extra_context) + +@login_required +def edit_talk(request, scope, id, template_name='talk/edit-talk.html'): + """Allows users that submitted a talk to edit it until the talk is approved. + """ + + talk = Talk.objects.get(pk=id) + + if talk.approved == True: + redirect_to = reverse('scipycon_account', kwargs={'scope': scope}) + return set_message_cookie(redirect_to, + msg = u'Sorry but you cannot edit the talk once'\ + + ' it has been accepted.') + + if talk.speaker != request.user: + redirect_to = reverse('scipycon_account', kwargs={'scope': scope}) + return set_message_cookie(redirect_to, + msg = u'Redirected to account because the talk you selected' \ + + ' is not your own.') + + if request.method == 'POST': + form = TalkEditForm(data=request.POST) + if form.is_valid(): + talk.slug = slugify(form.data.get('title')) + talk.authors_bio = form.data.get('authors_bio') + talk.contact = form.data.get('contact') + talk.title = form.data.get('title') + talk.abstract = form.data.get('abstract') + talk.topic = form.data.get('topic') + talk.duration = form.data.get('duration') + talk.audience = form.data.get('audience') + talk.save() + + # Saved.. redirect + redirect_to = reverse('scipycon_edit_talk', + kwargs={'scope': scope, 'id': talk.id}) + return set_message_cookie(redirect_to, + msg = u'Your changes have been saved.') + else: + form = TalkEditForm(initial={ + 'id' : id, + 'authors_bio' : talk.authors_bio, + 'contact' : talk.contact, + 'title' : talk.title, + 'abstract' : talk.abstract, + 'topic' : talk.topic, + 'duration' : talk.duration, + 'audience' : talk.audience, + }) + + context = locals() + context['params'] = {'scope': scope} + + return render_to_response(template_name, RequestContext(request, context)) + +@login_required() +def submit_talk(request, scope, template_name='talk/submit-talk.html'): + """Allows user to edit profile + """ + + scope_entity = Event.objects.get(scope=scope) + + user = request.user + if user.is_authenticated(): + try: + profile = user.get_profile() + except: + profile, new = UserProfile.objects.get_or_create( + user=user, scope=scope_entity) + if new: + profile.save() + + message = None + + if request.method == 'POST': + talk_form = TalkSubmitForm(data=request.POST) + + register_form = RegisterForm(data=request.POST, files=request.FILES) + + if request.POST.get('action', None) == 'login': + login_form = AuthenticationForm(data=request.POST) + if login_form.is_valid(): + + from django.contrib.auth import login + login(request, login_form.get_user()) + + redirect_to = reverse('scipycon_submit_talk', + kwargs={'scope': scope}) + return set_message_cookie(redirect_to, + msg = u'You have been logged in.') + + if request.POST.get('action', None) == 'register': + # add the new user + if register_form.is_valid(): + + user = scipycon_createuser(request, register_form.data) + + if talk_form.is_valid(): + if user.is_authenticated(): + title = talk_form.data.get('title') + talk = Talk.objects.create( + slug = slugify(title), + scope = scope_entity, + speaker = User.objects.get(pk=user.id), + authors_bio = talk_form.data.get('authors_bio'), + contact = talk_form.data.get('contact'), + title = talk_form.data.get('title'), + abstract = talk_form.data.get('abstract'), + topic = talk_form.data.get('topic'), + duration = talk_form.data.get('duration'), + audience = talk_form.data.get('audience'), + approved = False, +# tags = talk_form.data.get('tags') + ) + talk.save() + # Saved, ... redirect back to account + redirect_to = reverse('scipycon_edit_talk', + kwargs={'scope': scope, 'id': talk.id}) + return set_message_cookie(redirect_to, + msg = u'Thanks, your talk has been submitted.') + else: + redirect_to = reverse('scipycon_submit_talk', + kwargs={'scope': scope}) + return set_message_cookie(redirect_to, + msg = u'Something is wrong here.') + + else: + talk_form = TalkSubmitForm() + register_form = RegisterForm() + login_form = AuthenticationForm() + + + return render_to_response(template_name, RequestContext(request, { + 'params': {'scope': scope}, + 'talk_form': talk_form, + 'register_form' : register_form, + 'message' : message, + 'login_form' : login_form + })) + +def list_talks(request, scope, template_name='talk/list-all-talks.html'): + """List all the tasks submitted by a user. + """ + + talks = Talk.objects.filter(approved=True) + + return render_to_response(template_name, RequestContext(request, { + 'params': {'scope': scope}, + 'talk_list': talks, + })) + +def download_slides(request, scope): + """View that lets users allow to download the slides they want. + """ + + template_name = 'talk/download-slides.html' + return render_to_response(template_name, RequestContext(request, { + 'params': {'scope': scope}, + })) + +def download_videos(request, scope): + """View that gives users the link to the videos + """ + + template_name = 'talk/download-videos.html' + return render_to_response(template_name, RequestContext(request, { + 'params': {'scope': scope}, + })) diff --git a/project/scipycon/user/__init__.py b/project/scipycon/user/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/project/scipycon/user/__init__.py diff --git a/project/scipycon/user/admin.py b/project/scipycon/user/admin.py new file mode 100644 index 0000000..3d4813b --- /dev/null +++ b/project/scipycon/user/admin.py @@ -0,0 +1,17 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import + +#django +from django.contrib import admin + +#scipycon +from .models import UserProfile + +class UserProfileAdmin(admin.ModelAdmin): + list_display = ('user', 'email', 'url', 'about') + + def email(self, obj): + return obj.user.email + +admin.site.register(UserProfile, UserProfileAdmin) + diff --git a/project/scipycon/user/forms.py b/project/scipycon/user/forms.py new file mode 100644 index 0000000..46ad2f6 --- /dev/null +++ b/project/scipycon/user/forms.py @@ -0,0 +1,135 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import + +#django +from django import forms +from django.contrib.auth.models import User + +class RegistrantForm(forms.Form): + """Form to register an attendee + """ + username = forms.RegexField(label="Nickname", max_length=30, + regex=r'^\w+$', + help_text = "30 characters or fewer. Alphanumeric" \ + + " characters only (letters, digits and underscores).", + error_message = "This value must contain only letters, numbers and underscores.") + name = forms.CharField(label=u"Name", max_length=50, required=True) + email = forms.EmailField(label=u"E-mail", max_length=50, required=True) + + def clean_email(self): + """Validates that the entered e-mail is unique. + """ + email = self.cleaned_data.get("email") + if email and User.objects.filter(email=email).count() > 0: + raise forms.ValidationError( + u"That email address is already in use. Are you a member of " \ + "site? Please log in.") + + return email + + def clean_username(self): + """Validates that the entered username is unique. + """ + username = self.cleaned_data.get("username") + if username and User.objects.filter(username=username).count() > 0: + raise forms.ValidationError( + u"That username is already in use.") + + return username + +class RegisterForm(forms.Form): + """Form to register speaker + """ + username = forms.RegexField(label="Username", max_length=30, + regex=r'^\w+$', + help_text = "Required. 30 characters or fewer. Alphanumeric" \ + + " characters only (letters, digits and underscores).", + error_message = "This value must contain only letters, numbers and underscores.") + first_name = forms.CharField(label=u"First name", max_length=50) + last_name = forms.CharField(label=u"Last name", max_length=50) + email = forms.EmailField(label=u"E-mail", max_length=50) + url = forms.URLField(required=False) + about = forms.CharField(label=u'Short Bio', max_length=50, required=False) + photo = forms.FileField(label=u'Profile Photo', required=False) + password_1 = forms.CharField( + label=u"Password", widget=forms.PasswordInput(), max_length=20) + password_2 = forms.CharField( + label=u"Confirm password", widget=forms.PasswordInput(), max_length=20) + + def clean_password_2(self): + """Validates that password 1 and password 2 are the same. + """ + p1 = self.cleaned_data.get('password_1') + p2 = self.cleaned_data.get('password_2') + + if not (p1 and p2 and p1 == p2): + raise forms.ValidationError(u"The two passwords do not match.") + + return p2 + + def clean_email(self): + """Validates that the entered e-mail is unique. + """ + email = self.cleaned_data.get("email") + if email and User.objects.filter(email=email).count() > 0: + raise forms.ValidationError( + u"That email address is already in use.") + + return email + + def clean_username(self): + """Validates that the entered username is unique. + """ + username = self.cleaned_data.get("username") + if username and User.objects.filter(username=username).count() > 0: + raise forms.ValidationError( + u"That username is already in use.") + + return username + +class EditProfileForm(forms.Form): + """Edit user profile form + """ + first_name = forms.CharField(max_length=50) + last_name = forms.CharField(max_length=50) + email = forms.EmailField(max_length=50) + email2 = forms.CharField(widget=forms.HiddenInput) + url = forms.URLField(required=False) + about = forms.CharField(label=u'Short Bio', + widget=forms.Textarea, required=False) + photo = forms.FileField(label=u'Profile Photo', + required=False) + + def clean_email(self): + """Validates that the entered e-mail is unique. + """ + email = self.cleaned_data.get("email") + email2 = self.data.get("email2").strip() + print email, email2 + if email != email2: # email has been changed + if email and User.objects.filter(email=email).count() > 0: + raise forms.ValidationError( + u"That email address is already in use.") + + return email + +class UsernameForm(forms.Form): + """Form to edit email address + """ + username = forms.RegexField(label="Username", max_length=30, + regex=r'^\w+$', + help_text = "Required. 30 characters or fewer. Alphanumeric" \ + + " characters only (letters, digits and underscores).", + error_message = "This value must contain only letters, numbers and underscores.") + + def clean_username(self): + """Validates that the entered username is unique. + """ + username = self.cleaned_data.get("username") + if username and User.objects.filter(username=username).count() > 0: + raise forms.ValidationError( + u"That username is already in use.") + + return username + + diff --git a/project/scipycon/user/models.py b/project/scipycon/user/models.py new file mode 100644 index 0000000..4688b79 --- /dev/null +++ b/project/scipycon/user/models.py @@ -0,0 +1,26 @@ +from django.db import models +from django.conf import settings +from django.db.models.signals import post_save +from django.contrib.auth.models import User + +from project.scipycon.base import models as base_models + + +class UserProfile(base_models.ScopedBase): + """Extend atributes for django User + """ + + user = models.ForeignKey(User, unique=True) + + url = models.URLField(blank=True, verify_exists=False) + + photo = models.CharField(max_length=64, blank=True) + + about = models.TextField(blank=True) + + def __unicode__(self): + return 'UserProfile for user: <%s %s> %s' % (self.user.first_name, + self.user.last_name, self.user.email) + + def fullname(self): + return '%s %s' % (self.user.first_name, self.user.last_name) diff --git a/project/scipycon/user/utils.py b/project/scipycon/user/utils.py new file mode 100644 index 0000000..f4b4741 --- /dev/null +++ b/project/scipycon/user/utils.py @@ -0,0 +1,138 @@ +import os + +from django.conf import settings +from django.core.exceptions import ObjectDoesNotExist +from django.contrib.auth.models import User + +from PIL import Image + +from project.scipycon.base.models import Event +from project.scipycon.user.models import UserProfile + + +def scipycon_createregistrant(request, data, scope): + """Create user + """ + + email = data.get('email') + name = data.get('name') + username = data.get('username') + + n = name.split(' ') + if len(n) > 1: + first_name = ' '.join(n[:-1]) + last_name = n[-1] + else: + first_name = '' + last_name = n[0] + + + # Create user + user = User.objects.create_user(username=username, email=email) + user.first_name = first_name + user.last_name = last_name + user.save() + + scope_entity = Event.objects.get(scope=scope) + try: + profile = user.get_profile() + except: + profile, new = UserProfile.objects.get_or_create( + user=user, scope=scope_entity) + profile.save() + + return user + +def scipycon_createuser(request, data, scope): + """Create user + """ + + from django.contrib.auth import authenticate + from django.contrib.auth import login + + email = data.get('email') + username = data.get('username') + password = data.get('password_1') + password = data.get('password_1') + + # Create user + user = User.objects.create_user( + username=username, email=email, password=password) + user.first_name = data.get('first_name') + user.last_name = data.get('last_name') + user.save() + + # Log in user + + user = authenticate(username=username, password=password) + + login(request, user) + + scope_entity = Event.objects.get(scope=scope) + + try: + profile = user.get_profile() + except: + profile, new = UserProfile.objects.get_or_create( + user=user, scope=scope_entity) + + photo = request.FILES.get('photo', None) + filename= None + if photo: + filename = handle_uploaded_photo(user, request.FILES['photo']) + if filename: + profile.photo = filename + + profile.url = data.get('url') + profile.about = data.get('about') + profile.save() + + return user + +def handle_uploaded_photo(user, ufile): + """Handles the upload and gives the file path to be saved. + """ + + usermedia = settings.USER_MEDIA_ROOT + filename = ufile.name + ext = filename.split('.')[-1] + + filecontent = ufile.read() + userfilename = 'user-%d.%s' % (user.id, ext) + if not filecontent: + return None + + #save + foutname = os.path.join(usermedia, userfilename) + + fout = file(foutname, 'wb') + fout.write(filecontent) + fout.close() + + # crop and resize + image = Image.open(foutname) + pw = image.size[0] + ph = image.size[1] + nw = nh = 80 + if (pw, ph) != (nw, nh): + pr = float(pw) / float(ph) + nr = float(nw) / float(nh) + + if pr > nr: + # photo aspect is wider than destination ratio + tw = int(round(nh * pr)) + image = image.resize((tw, nh), Image.ANTIALIAS) + l = int(round(( tw - nw ) / 2.0)) + image = image.crop((l, 0, l + nw, nh)) + elif pr < nr: + # photo aspect is taller than destination ratio + th = int(round(nw / pr)) + image = image.resize((nw, th), Image.ANTIALIAS) + t = int(round(( th - nh ) / 2.0)) + image = image.crop((0, t, nw, t + nh)) + else: + # photo aspect matches the destination ratio + image = image.resize((nw, nh), Image.ANTIALIAS) + + image.save(str(foutname)) + return userfilename diff --git a/project/scipycon/user/views.py b/project/scipycon/user/views.py new file mode 100644 index 0000000..d46e77d --- /dev/null +++ b/project/scipycon/user/views.py @@ -0,0 +1,386 @@ +from urlparse import urlparse + +import simplejson as json +import os + +from django.conf import settings +from django.contrib.auth.decorators import login_required +from django.contrib.auth.forms import AuthenticationForm +from django.contrib.auth.forms import PasswordChangeForm +from django.contrib.auth.models import User +from django.core.exceptions import ObjectDoesNotExist +from django.core.urlresolvers import reverse +from django.db.models import Q +from django.http import HttpResponse +from django.shortcuts import render_to_response +from django.template import RequestContext + +from PIL import Image + +from project.scipycon.base.models import Event +from project.scipycon.registration.models import Registration +from project.scipycon.registration.models import Wifi +from project.scipycon.registration.forms import WifiForm +from project.scipycon.talk.models import Talk +from project.scipycon.user.forms import EditProfileForm +from project.scipycon.user.forms import RegisterForm +from project.scipycon.user.forms import UsernameForm +from project.scipycon.user.utils import handle_uploaded_photo +from project.scipycon.user.utils import scipycon_createuser +from project.scipycon.utils import set_message_cookie + +#User_dump Http404 Error +from django.http import Http404 +#for user_dump creation +from project.scipycon.registration.models import Accommodation + +#Pdf badge generation +from reportlab.pdfgen import canvas +from reportlab.lib.units import cm +from reportlab.platypus import Image as reportlabImage +from django.core.exceptions import ObjectDoesNotExist + + +@login_required +def account(request, scope, template_name="user/account.html"): + """Displays the main screen of the current user's account. + """ + + user = request.user + profile = user.get_profile() + + talks = Talk.objects.filter(speaker=user) + + try: + registration = Registration.objects.get(registrant=user) + except ObjectDoesNotExist: + registration = None + + try: + wifiobj = Wifi.objects.get(user=user) + except ObjectDoesNotExist: + wifiobj = None + + event = Event.objects.get(scope=scope) + + if profile.photo: + photo = os.path.join(settings.USER_MEDIA_URL, profile.photo) + else: + photo = '/img/user-default.png' + + return render_to_response(template_name, RequestContext(request, { + 'params': {'scope': scope}, + 'user' : user, + 'profile' : profile, + 'photo' : photo, + 'talks' : talks, + 'registration' : registration, + 'event': event})) + +@login_required +def edit_profile(request, scope, template_name="user/editprofile.html"): + """Allows user to edit profile + """ + + user = request.user + profile = user.get_profile() + + if request.method == "POST": + form = EditProfileForm(data=request.POST, + files=request.FILES) + + if form.is_valid(): + photo = request.FILES.get('photo', None) + filename= None + if photo: + filename = handle_uploaded_photo(user, request.FILES['photo']) + if filename: + profile.photo = filename + + user.email = form.data.get("email") + user.first_name = form.data.get("first_name") + user.last_name = form.data.get("last_name") + user.save() + + profile.url = form.data.get("url") + profile.about = form.data.get("about") + profile.save() + + redirect_to = reverse('scipycon_account', + kwargs={'scope': scope}) + return set_message_cookie(redirect_to, + msg = u'Your profile has been changed.') + + else: + form = EditProfileForm( + initial={ + 'email' : user.email, + 'email2' : user.email, # hidden field + 'first_name' : user.first_name, + 'last_name' : user.last_name, + 'url' : profile.url, + 'about' : profile.about, + }) + + return render_to_response(template_name, RequestContext(request, { + 'params': {'scope': scope}, + 'form': form + })) + +def login(request, scope, template_name="user/login.html"): + """Custom view to login or register/login a user. + Integration of register and login form + It uses Django's standard AuthenticationForm, though. + """ + + user = request.user + if user.is_authenticated(): + redirect_to = reverse("scipycon_account", kwargs={'scope': scope}) + return set_message_cookie(redirect_to, + msg = u"Redirected to account from login form.") + + # Using Djangos default AuthenticationForm + login_form = AuthenticationForm() + register_form = RegisterForm() + + if request.POST.get("action") == "login": + login_form = AuthenticationForm(data=request.POST) + + if login_form.is_valid(): + redirect_to = request.POST.get("next") + # Light security check -- make sure redirect_to isn't garbage. + if not redirect_to or '//' in redirect_to or ' ' in redirect_to: + redirect_to = reverse('scipycon_account', + kwargs={'scope': scope}) + + from django.contrib.auth import login + login(request, login_form.get_user()) + + return set_message_cookie(redirect_to, msg = u"You have been logged in.") + + elif request.POST.get("action") == "register": + register_form = RegisterForm(data=request.POST) + if register_form.is_valid(): + + user = scipycon_createuser(request, register_form.data, scope) + + redirect_to = request.POST.get("next") + if not redirect_to or '//' in redirect_to or ' ' in redirect_to: + redirect_to = reverse('scipycon_account', + kwargs={'scope': scope}) + + return set_message_cookie( + redirect_to, msg = u"You have been registered and logged in.") + + # Get next_url + next_url = request.REQUEST.get("next") + if next_url is None: + next_url = request.META.get("HTTP_REFERER") + if next_url is None: + next_url = reverse('scipycon_account', kwargs={'scope': scope}) + + # Get just the path of the url. + # See django.contrib.auth.views.login for more + next_url = urlparse(next_url) + next_url = next_url[2] + + try: + login_form_errors = login_form.errors["__all__"] + except KeyError: + login_form_errors = None + + return render_to_response(template_name, RequestContext(request, { + 'params': {'scope': scope}, + 'login_form' : login_form, + 'login_form_errors' : login_form_errors, + 'register_form' : register_form, + 'next_url' : next_url, + })) + +def logout(request, scope): + """Custom method to logout a user. + + The reason to use a custom logout method is just to provide a login and a + logoutmethod on one place. + """ + + from django.contrib.auth import logout + logout(request) + + redirect_to = '/%s' % (scope) + return set_message_cookie(redirect_to, msg = u"You have been logged out.") + +@login_required +def password(request, scope, template_name='user/password.html'): + """Changes the password of current user. + """ + + if request.method == 'POST': + form = PasswordChangeForm(request.user, request.POST) + if form.is_valid(): + form.save() + redirect_to = reverse('scipycon_account', kwargs={'scope': scope}) + return set_message_cookie(redirect_to, + msg = u'Your password has been changed.') + else: + form = PasswordChangeForm(request.user) + + return render_to_response(template_name, RequestContext(request, { + 'params': {'scope': scope}, + 'form' : form + })) + +@login_required +def username(request, scope, template_name='user/username.html'): + """Saves the username from the data form. + """ + if request.method == 'POST': + username_form = UsernameForm( + initial={'username' : request.user.username}, + data=request.POST) + if username_form.is_valid(): + request.user.username = username_form.cleaned_data.get("username") + request.user.save() + redirect_to = reverse('scipycon_account', + kwargs={'scope': scope}) + return set_message_cookie(redirect_to, + msg = u"Your username has been changed.") + else: + username_form = UsernameForm(initial={"username" : request.user.username}) + + return render_to_response(template_name, RequestContext(request, { + 'params': {'scope': scope}, + 'form': username_form + })) + + +def get_usernames(request, scope): + """Returns in json the list of ten possible usernames + starting with the last pattern in the comma separated string + """ + + get_params = request.GET + authors_str = get_params.get('input') + + if not authors_str: + return HttpResponse(json.dumps('')) + + authors = authors_str.split(',') + search_author = authors[-1].strip() + + users = User.objects.filter( + Q(username__istartswith=search_author) | Q( + first_name__istartswith=search_author) | Q( + last_name__istartswith=search_author)) + + results = [{'id': '', + 'info': 'plugin_header', + 'value': 'User Names' + }] + + for user in users: + results.append( + {'id': 'author_name', + 'info': str(user.get_full_name()), + 'value': str(user.username) + }) + + json_response = {'results': results} + + return HttpResponse(json.dumps(json_response)) + + +@login_required +def get_user_dump(request, scope,template_name='user/dump.html'): + """ Gets a general dump of user related info + """ + print request.user.is_staff + if request.user.is_staff: + qs=Registration.objects.all() + rows=[] + for obj in qs: + row = {} + row['first_name'] = obj.registrant.first_name + row['last_name'] = obj.registrant.last_name + try: + accomodation_require = Accommodation.objects.filter(user__username=obj.registrant.username)[0] + row['sex'] = accomodation_require.sex + except: + row['sex'] = '-' + row['city'] = obj.city + row['organization'] = obj.organisation + row['occupation'] = obj.occupation + row['conference'] = obj.conference + row['sprint'] = obj.sprint + row['tutorial'] = obj.tutorial + try: + wifi_require = Wifi.objects.filter(user__username=obj.registrant.username)[0] + row['wifi'] = wifi_require.wifi + except: + row['wifi']='Wifi Unspecified' + rows.append(row) + return render_to_response(template_name, RequestContext(request, { + 'rows': rows})) + + + else: + raise Http404 + + +@login_required +def badge(request,scope): + + from django.conf import settings + + # Create the HttpResponse object with the appropriate PDF headers. + response = HttpResponse(mimetype='application/pdf') + response['Content-Disposition'] = 'attachment; filename=scipybadge.pdf' + + # Create the PDF object, using the response object as its "file." + c = canvas.Canvas(response) + + ref=5*cm + # Draw things on the PDF. Here's where the PDF generation happens. + # See the ReportLab documentation for the full list of functionality. + c.rect(ref,ref,9*cm,6*cm) + + img_path = os.path.join(settings.STATIC_ROOT, 'img', 'scipyshiny_small.png') + im = reportlabImage(img_path, width=1.75*cm, height=1.75*cm) + im.drawOn(c,(ref+0.8*cm),(ref+4.3*cm)) + c.setFont('Helvetica', 6) + c.drawString((ref+1.0*cm),(ref+4.2*cm),'scipy.in 2010') + c.drawString((ref+1.1*cm),(ref+4.0*cm),'Hyderabad') + + c.setFont('Helvetica', 14) + print request.user.id + reg_obj=Registration.objects.get(registrant=request.user.id) + c.drawString((ref+3.4*cm),(ref+4.9*cm),str(reg_obj.slug)) + + c.setFont('Helvetica-Bold', 15) + c.drawString((ref+0.6*cm),(ref+3.4*cm),str(request.user.get_full_name())) + c.setFont('Helvetica', 11) + c.drawString((ref+2.8*cm),(ref+2.7*cm),reg_obj.organisation) + c.setFont('Helvetica', 11) + try: + c.drawString((ref+2.8*cm),(ref+2.2*cm),reg_obj.occupation.split(':')[1]) + except IndexError: + c.drawString((ref+2.8*cm),(ref+2.3*cm),reg_obj.occupation) + + c.setFont('Helvetica', 10) + c.drawString((ref+2.8*cm),(ref+1.7*cm),reg_obj.city) + c.setFont('Helvetica', 10) + c.drawString((ref+2.8*cm),(ref+1*cm),'Participant') + + + try: + wifi_obj=Wifi.objects.get(user=request.user.id) + c.setFont('Helvetica', 10) + c.drawString((ref+5.6*cm),(ref+0.5*cm),wifi_obj.registration_id) + except : + pass + + + # Close the PDF object cleanly, and we're done. + c.showPage() + c.save() + return response diff --git a/project/scipycon/utils.py b/project/scipycon/utils.py new file mode 100644 index 0000000..93331b7 --- /dev/null +++ b/project/scipycon/utils.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +#python +import urllib +import datetime +import re +from random import randint + +#django +from django.http import HttpResponseRedirect + +def scipycon_quote(string, encoding="utf-8"): + """Encodes string to encoding before quoting. + """ + return urllib.quote(string.encode(encoding)) + +# from LFS +def set_message_cookie(url, msg): + """Creates response object with given url and adds message cookie with passed + message. + """ + + # We just keep the message two seconds. + max_age = 2 + expires = datetime.datetime.strftime( + datetime.datetime.utcnow() + + datetime.timedelta(seconds=max_age), "%a, %d-%b-%Y %H:%M:%S GMT") + + response = HttpResponseRedirect(url) + response.set_cookie("message", scipycon_quote(msg), max_age=max_age, expires=expires) + + return response + +# from django-snippets +def slugify(inStr): + removelist = ["a", "an", "as", "at", "before", "but", "by", "for","from","is", "in", "into", "like", "of", "off", "on", "onto","per","since", "than", "the", "this", "that", "to", "up", "via","with"]; + for a in removelist: + aslug = re.sub(r'\b'+a+r'\b','',inStr) + aslug = re.sub('[^\w\s-]', '', aslug).strip().lower() + aslug = re.sub('\s+', '-', aslug) + return len(aslug) > 50 and '%s-%d' % (aslug[:43], randint(100000,999999)) or aslug diff --git a/project/scipycon/views.py b/project/scipycon/views.py new file mode 100644 index 0000000..74dde7b --- /dev/null +++ b/project/scipycon/views.py @@ -0,0 +1,22 @@ +from django.shortcuts import render_to_response +from django.template import RequestContext +from django.conf import settings + + +def handler404(request, template_name='404.html'): + """ + Loads 404 page while passing scope + """ + scope = settings.CURRENT_SCOPE + return render_to_response(template_name, RequestContext(request, { + 'params': {'scope': scope}, + })) + +def handler500(request, template_name='500.html'): + """ + Loads 500 page while passing scope + """ + scope = settings.CURRENT_SCOPE + return render_to_response(template_name, RequestContext(request, { + 'params': {'scope': scope}, + })) |