summaryrefslogtreecommitdiff
path: root/project/scipycon
diff options
context:
space:
mode:
Diffstat (limited to 'project/scipycon')
-rw-r--r--project/scipycon/__init__.py0
-rw-r--r--project/scipycon/base/__init__.py0
-rw-r--r--project/scipycon/base/admin.py45
-rw-r--r--project/scipycon/base/models.py81
-rw-r--r--project/scipycon/proceedings/__init__.py0
-rw-r--r--project/scipycon/proceedings/admin.py16
-rw-r--r--project/scipycon/proceedings/booklet/__init__.py0
-rw-r--r--project/scipycon/proceedings/booklet/mk_booklet.py94
-rw-r--r--project/scipycon/proceedings/booklet/mk_scipy_paper.py463
-rw-r--r--project/scipycon/proceedings/forms.py30
-rw-r--r--project/scipycon/proceedings/models.py32
-rw-r--r--project/scipycon/proceedings/views.py203
-rw-r--r--project/scipycon/registration/__init__.py0
-rw-r--r--project/scipycon/registration/admin.py59
-rw-r--r--project/scipycon/registration/forms.py251
-rw-r--r--project/scipycon/registration/labels.py7
-rw-r--r--project/scipycon/registration/migrations/0001_initial.py192
-rw-r--r--project/scipycon/registration/migrations/0002_auto__add_field_payment_acco_confirmed.py117
-rw-r--r--project/scipycon/registration/migrations/0003_auto__add_field_payment_date_confirmed.py118
-rw-r--r--project/scipycon/registration/migrations/0004_auto__chg_field_payment_date_confirmed.py118
-rw-r--r--project/scipycon/registration/migrations/0005_auto__add_field_payment_confirmed_mail__add_field_payment_acco_confirm.py126
-rw-r--r--project/scipycon/registration/migrations/0006_auto__add_field_accommodation_accommodation_on_1st__add_field_accommod.py156
-rw-r--r--project/scipycon/registration/migrations/__init__.py0
-rw-r--r--project/scipycon/registration/models.py167
-rw-r--r--project/scipycon/registration/tests.py19
-rw-r--r--project/scipycon/registration/utils.py38
-rw-r--r--project/scipycon/registration/views.py583
-rw-r--r--project/scipycon/talk/__init__.py0
-rw-r--r--project/scipycon/talk/admin.py23
-rw-r--r--project/scipycon/talk/forms.py62
-rw-r--r--project/scipycon/talk/models.py57
-rw-r--r--project/scipycon/talk/templatetags/__init__.py1
-rw-r--r--project/scipycon/talk/templatetags/talk_extras.py8
-rw-r--r--project/scipycon/talk/views.py225
-rw-r--r--project/scipycon/user/__init__.py0
-rw-r--r--project/scipycon/user/admin.py17
-rw-r--r--project/scipycon/user/forms.py135
-rw-r--r--project/scipycon/user/models.py26
-rw-r--r--project/scipycon/user/utils.py138
-rw-r--r--project/scipycon/user/views.py386
-rw-r--r--project/scipycon/utils.py40
-rw-r--r--project/scipycon/views.py22
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},
+ }))