codekasten/umfrage_kirchenplatz2012/src/umfrage.py

184 lines
5.9 KiB
Python
Raw Normal View History

#!/usr/bin/env python2.6
# -*- coding: utf-8 -*-
import os
# the basedir is the parent dir of the location of this script
BASE_DIR = os.path.dirname(os.path.abspath(os.path.join(__file__, os.path.pardir)))
# add the project directory to the python search path
import sys
sys.path.insert(0, os.path.join(BASE_DIR, "src"))
from dataset import DEFINITION_OPTIONS, DEFINITION_QUALITY_RANGES, \
DEFINITION_QUESTIONS
import ConfigParser
import datetime
import uuid
import sqlobject
import bobo
import genshi
import genshi.template
import genshi.filters
CONFIG_FILE = os.path.join(BASE_DIR, "umfrage.conf")
config = ConfigParser.SafeConfigParser()
config.read(CONFIG_FILE)
db_uri = config.get("database", "uri")
sqlobject.sqlhub.processConnection = sqlobject.connectionForURI(db_uri)
loader = genshi.template.TemplateLoader(os.path.join(BASE_DIR, 'templates'), auto_reload=False)
BASE_DICT = {
"base_url": "/umfrage/kirchenplatz2012/", # the trailing slash is necessary
"errors": {},
}
class Session(sqlobject.SQLObject):
created = sqlobject.DateTimeCol(default=sqlobject.DateTimeCol.now)
name = sqlobject.UnicodeCol(default=lambda: uuid.uuid4().hex)
class Question(sqlobject.SQLObject):
text = sqlobject.UnicodeCol()
weight = sqlobject.IntCol()
quality_levels = sqlobject.PickleCol()
class Option(sqlobject.SQLObject):
title = sqlobject.UnicodeCol()
text = sqlobject.UnicodeCol()
image = sqlobject.UnicodeCol()
weight = sqlobject.IntCol()
class Answer(sqlobject.SQLObject):
text = sqlobject.UnicodeCol(default="")
quality = sqlobject.UnicodeCol(default="")
question = sqlobject.ForeignKey("Question")
option = sqlobject.ForeignKey("Option")
session = sqlobject.ForeignKey("Session")
def get_default_values(**kwargs):
value_dict = dict(BASE_DICT)
# we always need "options" (e.g. on frontpage)
value_dict["options"] = list(Option.select())
value_dict["options"].sort(key=lambda item: item.weight)
for key, value in kwargs.items():
value_dict[key] = value
return value_dict
def render(filename, input_data=None, **values):
stream = loader.load(filename).generate(**values)
if not input_data is None:
stream |= genshi.filters.HTMLFormFiller(data=input_data)
return stream.render("html", doctype="html")
def get_previous_question(question):
questions = Question.select().orderBy("-weight")
for one_q in questions:
if one_q.weight < question.weight:
return one_q
return None
def get_next_question(question):
questions = Question.select().orderBy("weight")
for one_q in questions:
if one_q.weight > question.weight:
return one_q
return None
@bobo.query('/')
def show_question(session_id=None, question_id=None, go_backward=False,
**kwargs):
params = get_default_values()
session = None
if session_id:
session = list(Session.selectBy(name=session_id))
if session:
session = session[0]
if not session:
session = Session()
params["session"] = session
return render("start.html", **params)
question = None
if question_id:
try:
question = Question.get(int(question_id))
except ValueError:
pass
# any new input values? (update "Answer" objects)
target_question = None
if question:
for option in Option.select():
opt_params = {}
for key in ("text", "quality"):
dict_key = "option_%s_%s" % (option.id, key)
if dict_key in kwargs:
opt_params[key] = kwargs[dict_key]
# at least one item was found
if opt_params:
answer = Answer.selectBy(session=session, question=question,
option=option)
if not answer:
# create new one
answer = Answer(session=session, question=question,
option=option)
else:
answer = answer[0]
# update one value
for key in opt_params:
setattr(answer, key, opt_params[key])
if go_backward:
target_question = get_previous_question(question)
else:
target_question = get_next_question(question)
if not target_question:
# special case: we are finished
return render("summary.html", session=session)
if not target_question:
target_question = Question.select().orderBy("weight")[0]
# populate the next question
input_data = {}
for answer in Answer.selectBy(session=session, question=target_question):
for key in ("text", "quality"):
input_data["option_%s_%s" % (answer.option.id, key)] = \
getattr(answer, key)
params.update({"session": session,
"question": target_question,
"next_question": get_next_question(target_question),
"previous_question": get_previous_question(target_question),
})
return render("question.html", input_data=input_data, **params)
@bobo.query('')
def redirect_startpage():
return bobo.redirect(BASE_DICT["base_url"])
# initialize the tables (do it only once!)
if True:
tables = (Session, Question, Option, Answer)
# drop all
drop_tables = list(tables)
drop_tables.reverse()
for table in drop_tables:
if table.tableExists():
table.dropTable()
for table in tables:
table.createTable()
for index, (title, image_url, lines) in enumerate(DEFINITION_OPTIONS):
Option(title=title, image=image_url,
text=os.linesep.join(lines), weight=index)
for index, (text, quality_levels) in enumerate(DEFINITION_QUESTIONS):
Question(text=text, weight=index, quality_levels=DEFINITION_QUALITY_RANGES[quality_levels])
# this application should be usable with mod_wsgi
application = bobo.Application(bobo_resources=__name__)