From 81df603ba22eb640cb4fbd9ec036675e0d1b199c Mon Sep 17 00:00:00 2001
From: lars
Date: Thu, 15 Apr 2010 10:32:45 +0000
Subject: [PATCH] added changing of polls
---
wortschlucker/database.sqlite | Bin 3072 -> 4096 bytes
wortschlucker/templates/poll_admin.html | 36 ++++
.../templates/poll_admin_details.html | 25 +++
wortschlucker/templates/poll_new.html | 2 +-
wortschlucker/templates/polls.html | 2 +-
wortschlucker/wortschlucker.py | 170 ++++++++++++++++--
6 files changed, 217 insertions(+), 18 deletions(-)
create mode 100644 wortschlucker/templates/poll_admin.html
create mode 100644 wortschlucker/templates/poll_admin_details.html
diff --git a/wortschlucker/database.sqlite b/wortschlucker/database.sqlite
index 384bdb4b8d21f2819472fc882767a03214091112..04c9929b4c1fc1ffbcddb3b705250e6c76e5ac6d 100644
GIT binary patch
delta 658
zcmaKq%W4!s6o#iSIL#n}$}l2`1u{rv0(HMML7Yf$LS`ega3O@Mu4;2>yJNb?ATB1!
z6Bq^rw=Ui04P5&!zJfIqkx|6MS)9XvsPCMgI=goUKHk3*h|ZtUy&P@zq9EynpM&o~
za{2bt_?Okn$--4TQs5;RidK`WY
z)z$5IBb?W9(&&7CkF6+AoqPAeimu39$s8HUxggYGtf15y3zS1hm3Kgq|LdOhYHQz>W&QLom`oWy@*lu^
z+rNet&={*RH^M)T9Mi~Jy@M#siG_kN`OkqheR<&0RB)=BbsA0?OfmYB#6Eulh0d;!
delta 227
zcmZorXpop7CB(qafC^Y9>ez5FF+OErn#uTdvmi?;BUhs#GrPE`C}WfBr0RRrkHL3sr
diff --git a/wortschlucker/templates/poll_admin.html b/wortschlucker/templates/poll_admin.html
new file mode 100644
index 0000000..07cf631
--- /dev/null
+++ b/wortschlucker/templates/poll_admin.html
@@ -0,0 +1,36 @@
+
+
+
+
+
+ Poll settings
+
+
+ Poll properties
+
+
+
+
+
diff --git a/wortschlucker/templates/poll_admin_details.html b/wortschlucker/templates/poll_admin_details.html
new file mode 100644
index 0000000..50bc869
--- /dev/null
+++ b/wortschlucker/templates/poll_admin_details.html
@@ -0,0 +1,25 @@
+
+
+
+
+
+ Poll details
+
+
+ Poll: ${poll.title}
+
+
+
+
diff --git a/wortschlucker/templates/poll_new.html b/wortschlucker/templates/poll_new.html
index c096f7f..ca27017 100644
--- a/wortschlucker/templates/poll_new.html
+++ b/wortschlucker/templates/poll_new.html
@@ -26,7 +26,7 @@
${errors.description}
-
+
diff --git a/wortschlucker/templates/polls.html b/wortschlucker/templates/polls.html
index a808421..d2f465d 100644
--- a/wortschlucker/templates/polls.html
+++ b/wortschlucker/templates/polls.html
@@ -17,7 +17,7 @@
Create a new poll
-
-
+
Poll: ${poll.title} (${poll.get_num_of_submissions()}/${poll.get_num_of_submitters()})
diff --git a/wortschlucker/wortschlucker.py b/wortschlucker/wortschlucker.py
index 2fd5ad3..8bca1cf 100755
--- a/wortschlucker/wortschlucker.py
+++ b/wortschlucker/wortschlucker.py
@@ -8,6 +8,7 @@ import forms
import sqlobject
import bobo
from genshi.template import TemplateLoader
+import genshi.filters
import genshi
import formencode
import uuid
@@ -25,19 +26,46 @@ BASE_DICT = {
"errors": {},
}
+POLL_SETTINGS = {
+ "show_all_submissions": (bool, False),
+ "show_statistics": (bool, True),
+}
+
class WordSubmission(sqlobject.SQLObject):
submitter = sqlobject.StringCol()
content = sqlobject.StringCol()
poll_id = sqlobject.ForeignKey("Poll")
+class PollSetting(sqlobject.SQLObject):
+ poll_id = sqlobject.ForeignKey("Poll")
+ key = sqlobject.StringCol()
+ value = sqlobject.StringCol()
class Poll(sqlobject.SQLObject):
author = sqlobject.StringCol()
hash_key = sqlobject.StringCol()
+ admin_hash_key = sqlobject.StringCol()
title = sqlobject.StringCol()
description = sqlobject.StringCol()
timestamp_creation = sqlobject.DateTimeCol()
+ def get_settings(self):
+ current_dict = {}
+ for setting in PollSetting.selectBy(poll_id=self.id):
+ if setting.key in POLL_SETTINGS.keys():
+ current_dict[setting.key] = self.validate_poll_setting(setting.key, setting.value)
+ for key, meta_info in POLL_SETTINGS.items():
+ if not key in current_dict.keys():
+ current_dict[key] = meta_info[1]
+ return current_dict
+
+ def change_setting(self, key, value):
+ validated_value = self.validate_poll_setting(key, value)
+ if not validated_value is None:
+ poll_setting = PollSetting.selectBy(poll_id=self.id, key=key)
+ if poll_setting.count() == 1:
+ poll_setting.value = str(validated_value)
+
def get_num_of_submitters(self):
all_submitters = [submission.submitter for submission in WordSubmission.selectBy(poll_id=self.id)]
unique_submitters = []
@@ -52,17 +80,48 @@ class Poll(sqlobject.SQLObject):
def get_url(self):
return "%spolls/%s" % (BASE_DICT["base_url"], self.hash_key)
+ def get_admin_url(self):
+ return "%spolls/%s" % (BASE_DICT["base_url"], self.admin_hash_key)
+
+ def get_edit_url(self):
+ return "%spolls/%s/admin" % (BASE_DICT["base_url"], self.admin_hash_key)
+
def get_creation_time_string(self):
return str(self.timestamp_creation)
+
+def validate_poll_setting(key, value):
+ if not key in POLL_SETTINGS.keys():
+ return None
+ setting_type = POLL_SETTINGS[key][0]
+ if setting_type in (basestring, unicode, str):
+ return value
+ elif setting_type == bool:
+ text = value.tolower()
+ if text in ("0", "false", "no", "off", "disabled"):
+ return False
+ elif text in ("1", "true", "yes", "on", "enabled"):
+ return True
+ else:
+ return None
+ else:
+ # all other types (e.g. int, float, ...)
+ try:
+ return setting_type(value)
+ except ValueError:
+ return None
+
def get_default_values(**kwargs):
value_dict = dict(BASE_DICT)
for key, value in kwargs.items():
value_dict[key] = value
return value_dict
-def render(filename, **values):
- return loader.load(filename).generate(**values).render("html", doctype="html")
+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_poll_id(hash_key):
polls = Poll.selectBy(hash_key=hash_key)
@@ -71,22 +130,31 @@ def get_poll_id(hash_key):
else:
return None
+def get_poll_admin_id(hash_key):
+ polls = Poll.selectBy(admin_hash_key=hash_key)
+ if polls.count() == 1:
+ return polls[0].id
+ else:
+ return None
+
def get_new_hash_key():
hash_key = uuid.uuid4().get_hex()
- while not get_poll_id(hash_key) is None:
+ while (not get_poll_id(hash_key) is None) or (not get_poll_admin_id(hash_key) is None):
hash_key = uuid.uuid4().get_hex()
return hash_key
@bobo.query('/polls/new')
@bobo.query('/polls/new/:author/:title/:description')
-def create_poll(cancel=False, author=None, title=None, description=None):
- data = {"author": author, "title": title, "description": description}
+def new_poll(submit=None, cancel=None, author=None, title=None, description=None):
value_dict = get_default_values()
+ data = {"author": author, "title": title, "description": description}
if cancel:
return bobo.redirect(BASE_DICT["base_url"])
- elif (author is None) and (title is None) and (description is None):
- return render("poll_new.html", **value_dict)
+ elif not submit:
+ # show the "new poll" form
+ return render("poll_new.html", input_data=data, **value_dict)
else:
+ # create the new poll (if it is valid)
errors = {}
try:
data = forms.PollForm.to_python(data)
@@ -98,13 +166,75 @@ def create_poll(cancel=False, author=None, title=None, description=None):
else:
# create the new poll
hash_key = get_new_hash_key()
+ admin_hash_key = get_new_hash_key()
now = datetime.datetime.now()
- new_poll = Poll(hash_key=hash_key, timestamp_creation=now, **data)
- return bobo.redirect(new_poll.get_url())
+ new_poll = Poll(hash_key=hash_key, admin_hash_key=admin_hash_key, timestamp_creation=now, **data)
+ return bobo.redirect(new_poll.get_admin_url())
+
+@bobo.query('/polls/:admin_hash_key/admin')
+def admin_poll(cancel=False, submit=None, admin_hash_key=None, author=None, title=None, description=None, **kwargs):
+ value_dict = get_default_values()
+ data = {"author": author, "title": title, "description": description}
+ poll_id = get_poll_admin_id(admin_hash_key)
+ if poll_id is None:
+ return bobo.redirect(BASE_DICT["base_url"])
+ poll = Poll.get(poll_id)
+ # cancel: return to (non-edit) admin page
+ if cancel:
+ return bobo.redirect(poll.get_admin_url())
+ if author is None:
+ data["author"] = poll.author
+ if title is None:
+ data["title"] = poll.title
+ if description is None:
+ data["description"] = poll.description
+ settings = poll.get_settings()
+ # override with the given settings (taken from the form input with the prefix "setting_")
+ for setting_key, setting_value in kwargs.items():
+ if setting_key.startswith("setting_"):
+ real_key = setting_key[len("setting_"):]
+ if real_key in POLL_SETTINGS.keys():
+ valid_value = validate_poll_setting(real_key, setting_value)
+ if not valid_value is None:
+ settings[real_key] = valid_value
+ # store the new settings or create the new poll
+ errors = {}
+ if submit:
+ # check for errors only if the content is submitted (not just rendered)
+ try:
+ data = forms.PollForm.to_python(data)
+ except formencode.Invalid, errors_packed:
+ errors = errors_packed.unpack_errors()
+ # add "settings" after forms validation - since there is no destination type
+ data["settings"] = settings
+ # the admin hash should also not be validated - thus we may not add it before
+ if errors:
+ value_dict["errors"] = errors
+ return render("poll_admin.html", input_data=data, **value_dict)
+ else:
+ if submit:
+ # update core attributes of the existing poll
+ poll.author = data["author"]
+ poll.title = data["title"]
+ poll.description = data["description"]
+ current_settings = poll.get_settings()
+ # update settings
+ for key, value in settings.items():
+ if current_settings[key] != value:
+ poll.change_setting(key, value)
+ return bobo.redirect(poll.get_admin_url())
+ else:
+ return render("poll_admin.html", input_data=data, **value_dict)
@bobo.query('')
-@bobo.query('/')
+def base():
+ return bobo.redirect(BASE_DICT["base_url"])
+
@bobo.query('/polls')
+def base_polls():
+ return bobo.redirect(BASE_DICT["base_url"] + "polls/")
+
+@bobo.query('/')
@bobo.query('/polls/')
def show_polls():
value_dict = get_default_values()
@@ -113,20 +243,28 @@ def show_polls():
@bobo.query('/polls/:poll_hash')
def show_one_poll(poll_hash=None):
+ value_dict = get_default_values()
poll_id = get_poll_id(poll_hash)
if not poll_id is None:
- value_dict = get_default_values()
value_dict["poll"] = Poll.get(poll_id)
return render("poll_details.html", **value_dict)
else:
- return bobo.redirect(BASE_DICT["base_url"])
+ admin_poll_id = get_poll_admin_id(poll_hash)
+ if not admin_poll_id is None:
+ value_dict["poll"] = Poll.get(admin_poll_id)
+ return render("poll_admin_details.html", **value_dict)
+ else:
+ return bobo.redirect(BASE_DICT["base_url"])
-if not Poll.tableExists():
+for table in (Poll, WordSubmission, PollSetting):
#Poll.dropTable()
- Poll.createTable()
-if not WordSubmission.tableExists():
- WordSubmission.createTable()
+ if not table.tableExists():
+ table.createTable()
for poll in Poll.select():
print poll
+# this line allows to use wortschlucker with mod_wsgi
+# see: http://groups.google.com/group/bobo-web/msg/2ba55fc381658cd1
+#application = bobo.Application(bobo_resources=__name__)
+