Author: ianb
Date: 2005-04-03 20:18:01 -0600 (Sun, 03 Apr 2005)
New Revision: 2293
Added:
WSGIKit/trunk/examples/todo_sql/
WSGIKit/trunk/examples/todo_sql/__init__.py
WSGIKit/trunk/examples/todo_sql/db.py
WSGIKit/trunk/examples/todo_sql/server.conf
WSGIKit/trunk/examples/todo_sql/sitepage.py
WSGIKit/trunk/examples/todo_sql/templates/
WSGIKit/trunk/examples/todo_sql/templates/edit_list.pt
WSGIKit/trunk/examples/todo_sql/templates/generic_error.pt
WSGIKit/trunk/examples/todo_sql/templates/index.pt
WSGIKit/trunk/examples/todo_sql/templates/standard_template.pt
WSGIKit/trunk/examples/todo_sql/templates/view_list.pt
WSGIKit/trunk/examples/todo_sql/web/
WSGIKit/trunk/examples/todo_sql/web/__init__.py
WSGIKit/trunk/examples/todo_sql/web/edit_list.py
WSGIKit/trunk/examples/todo_sql/web/index.py
WSGIKit/trunk/examples/todo_sql/web/static/
WSGIKit/trunk/examples/todo_sql/web/static/stylesheet.css
WSGIKit/trunk/examples/todo_sql/web/view_list.py
Log:
Added simpler to-do example based on ZPT and SQLObject
Added: WSGIKit/trunk/examples/todo_sql/__init__.py
===================================================================
--- WSGIKit/trunk/examples/todo_sql/__init__.py 2005-04-04 02:17:38 UTC (rev 2292)
+++ WSGIKit/trunk/examples/todo_sql/__init__.py 2005-04-04 02:18:01 UTC (rev 2293)
@@ -0,0 +1,6 @@
+from wsgikit.util.thirdparty import add_package
+
+add_package('ZopePageTemplates')
+add_package('Component')
+add_package('ZPTKit')
+
Added: WSGIKit/trunk/examples/todo_sql/db.py
===================================================================
--- WSGIKit/trunk/examples/todo_sql/db.py 2005-04-04 02:17:38 UTC (rev 2292)
+++ WSGIKit/trunk/examples/todo_sql/db.py 2005-04-04 02:18:01 UTC (rev 2293)
@@ -0,0 +1,13 @@
+from sqlobject import *
+
+class TodoList(SQLObject):
+
+ description = StringCol(notNull=True)
+ items = MultipleJoin('TodoItem')
+
+class TodoItem(SQLObject):
+
+ todo_list = ForeignKey('TodoList')
+ description = StringCol(notNull=True)
+ done = BoolCol(notNull=True, default=False)
+
Added: WSGIKit/trunk/examples/todo_sql/server.conf
===================================================================
--- WSGIKit/trunk/examples/todo_sql/server.conf 2005-04-04 02:17:38 UTC (rev 2292)
+++ WSGIKit/trunk/examples/todo_sql/server.conf 2005-04-04 02:18:01 UTC (rev 2293)
@@ -0,0 +1,25 @@
+# -*- python -*- Note: this file is in Python syntax
+
+import os
+
+database = 'sqlite:%s/data.db' % os.path.dirname(__file__)
+
+sys_path = [os.path.dirname(__file__), # this package
+ os.path.dirname(os.path.dirname(__file__)), #wsgikit
+ '/home/ianb/colorstudy.com/trunk/SQLObject']
+
+app_template = 'webkit_zpt'
+app_name = ''
+webkit_dir = '/home/ianb/svn.w4py.org/WSGIKit/trunk/examples/todo_sql/web'
+
+## Server options:
+
+verbose = True
+# The name of the server-type to start:
+server = 'wsgiutils'
+# If true, files will be regularly polled and the server restarted
+# if files are modified:
+reload = True
+# If true, tracebacks will be shown in the browser:
+debug = True
+
Added: WSGIKit/trunk/examples/todo_sql/sitepage.py
===================================================================
--- WSGIKit/trunk/examples/todo_sql/sitepage.py 2005-04-04 02:17:38 UTC (rev 2292)
+++ WSGIKit/trunk/examples/todo_sql/sitepage.py 2005-04-04 02:18:01 UTC (rev 2293)
@@ -0,0 +1,63 @@
+import os
+import urllib
+from Component import CPage
+from Component.notify import NotifyComponent
+from ZPTKit import ZPTComponent
+from todo_sql.db import *
+
+class SitePage(CPage):
+
+ components = [
+ ZPTComponent([os.path.join(os.path.dirname(__file__),
+ 'templates')]),
+ NotifyComponent()]
+
+ def title(self):
+ return self.options.get('title', CPage.title(self))
+
+ def awake(self, trans):
+ CPage.awake(self, trans)
+ self.baseURL = self.request().environ()['.base_url']
+ self.url = URLBuilder(self.baseURL)
+ self.baseStaticURL = self.baseURL + '/static'
+ self.options.lists = list(TodoList.select())
+ self.setup()
+
+ def setup(self):
+ pass
+
+ def sleep(self, trans):
+ self.teardown()
+ CPage.sleep(self, trans)
+
+ def teardown(self):
+ pass
+
+ def writeHTML(self):
+ self.writeTemplate()
+
+
+class URLBuilder(object):
+
+ def __init__(self, url, kw=None):
+ self.url = url
+ self.kw = kw
+
+ def __getitem__(self, next):
+ return URLBuilder(self.url + '/' + next)
+
+ def __getattr__(self, next):
+ return self[next]
+
+ def __call__(self, *args, **kw):
+ if args:
+ new_url = self.url + '/' + '/'.join(args)
+ else:
+ new_url = self.url
+ return URLBuilder(new_url, kw)
+
+ def __str__(self):
+ if self.kw:
+ return self.url + '?' + urllib.urlencode(self.kw)
+ else:
+ return self.url
Added: WSGIKit/trunk/examples/todo_sql/templates/edit_list.pt
===================================================================
--- WSGIKit/trunk/examples/todo_sql/templates/edit_list.pt 2005-04-04 02:17:38 UTC (rev 2292)
+++ WSGIKit/trunk/examples/todo_sql/templates/edit_list.pt 2005-04-04 02:18:01 UTC (rev 2293)
@@ -0,0 +1,17 @@
+<html metal:use-macro="here/standard_template.pt/macros/page">
+<metal:body fill-slot="body">
+
+<form action="./edit_list" method="POST">
+<input type="hidden" name="_action_" value="save">
+<input type="hidden" name="id"
+ tal:attributes="value options/id">
+
+Description:<br>
+<input type="text" style="width: 100%" name="description"
+ tal:attributes="value options/list/description | nothing"><br>
+<input type="submit" value="Save">
+
+</form>
+
+</metal:body>
+</html>
Added: WSGIKit/trunk/examples/todo_sql/templates/generic_error.pt
===================================================================
--- WSGIKit/trunk/examples/todo_sql/templates/generic_error.pt 2005-04-04 02:17:38 UTC (rev 2292)
+++ WSGIKit/trunk/examples/todo_sql/templates/generic_error.pt 2005-04-04 02:18:01 UTC (rev 2293)
@@ -0,0 +1,7 @@
+<html metal:use-macro="here/standard_template.pt/macros/page">
+<metal:body fill-slot="body">
+
+<tal:block replace="structure options/error_message" />
+
+</metal:body>
+</html>
\ No newline at end of file
Added: WSGIKit/trunk/examples/todo_sql/templates/index.pt
===================================================================
--- WSGIKit/trunk/examples/todo_sql/templates/index.pt 2005-04-04 02:17:38 UTC (rev 2292)
+++ WSGIKit/trunk/examples/todo_sql/templates/index.pt 2005-04-04 02:18:01 UTC (rev 2293)
@@ -0,0 +1,24 @@
+<html metal:use-macro="here/standard_template.pt/macros/page">
+<metal:body fill-slot="body">
+
+
+<ul>
+ <li tal:repeat="list options/lists">
+ <a tal:attributes="href python: servlet.url.view_list(id=list.id)"
+ tal:content="list/description">list</a></li>
+</ul>
+
+<p tal:condition="not: options/lists">
+ There are no lists to display
+</p>
+
+<form action="./edit_list" method="POST">
+ Create a new list:<br>
+ <input type="hidden" name="id" value="new">
+ <input type="hidden" name="_action_" value="save">
+ <input type="text" name="description">
+ <input type="submit" value="Create">
+</form>
+
+</metal:body>
+</html>
Added: WSGIKit/trunk/examples/todo_sql/templates/standard_template.pt
===================================================================
--- WSGIKit/trunk/examples/todo_sql/templates/standard_template.pt 2005-04-04 02:17:38 UTC (rev 2292)
+++ WSGIKit/trunk/examples/todo_sql/templates/standard_template.pt 2005-04-04 02:18:01 UTC (rev 2293)
@@ -0,0 +1,42 @@
+<metal:tpl define-macro="page">
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
+ "http://www.w3.org/TR/REC-html40/loose.dtd">
+<html lang="en-US">
+<head>
+<title tal:content="servlet/title">title</title>
+<link rel="stylesheet" type="text/css"
+ tal:attributes="href python: servlet.baseStaticURL + '/stylesheet.css'">
+
+<metal:slot define-slot="extra_head"></metal:slot>
+
+</head>
+<body>
+
+<h1 id="header"><tal:mark replace="servlet/title"/></h1>
+
+<table width="100%">
+<tr>
+<td id="sidenav" width="20%">
+<a tal:attributes="href servlet/baseURL">Home</a><br>
+<tal:for repeat="list options/lists">
+ <a tal:attributes="href python: servlet.url.view_list(id=list.id)"
+ tal:content="list/description">link</a><br>
+</tal:for>
+</td>
+
+<td>
+<span tal:replace="structure servlet/messageText">
+This is where the notification messages go.
+</span>
+
+<div id="content">
+<metal:tpl define-slot="body">
+[This page has not customized its "body" slot]
+</metal:tpl>
+</div>
+
+</td></tr></table>
+
+</body>
+</html>
+</metal:tpl>
Added: WSGIKit/trunk/examples/todo_sql/templates/view_list.pt
===================================================================
--- WSGIKit/trunk/examples/todo_sql/templates/view_list.pt 2005-04-04 02:17:38 UTC (rev 2292)
+++ WSGIKit/trunk/examples/todo_sql/templates/view_list.pt 2005-04-04 02:18:01 UTC (rev 2293)
@@ -0,0 +1,54 @@
+<html metal:use-macro="here/standard_template.pt/macros/page">
+<metal:body fill-slot="body">
+
+<form action="view_list?_action_=check" method="POST">
+<input type="hidden" name="id"
+ tal:attributes="value options/list/id">
+
+<table>
+<tr>
+ <th>Done?</th>
+ <th>Description</th>
+</tr>
+
+<tr tal:repeat="item options/list_items">
+ <tal:let define="name python: 'item_%s' % item.id">
+ <td>
+ <input type="checkbox"
+ tal:attributes="name name;
+ id name;
+ checked item/done">
+ </td>
+ <td>
+ <label tal:attributes="for name"
+ tal:content="item/description">description</label>
+ </td>
+ </tal:let>
+</tr>
+
+<tr tal:condition="not: options/list_items">
+ <td colspan=2>No items to display</td>
+</tr>
+
+</table>
+
+<input type="submit" value="Update item status">
+</form>
+
+<form action="view_list?_action_=add" method="POST">
+<input type="hidden" name="id"
+ tal:attributes="value options/list/id">
+Add item:<br>
+<input type="text" style="width: 100%" name="description"><br>
+<input type="submit" value="Add">
+</form>
+
+<form action="edit_list?_action_=destroy" method="POST">
+<input type="hidden" name="id"
+ tal:attributes="value options/list/id">
+<input type="submit" value="Delete this list"
+ onclick="return window.confirm('Really delete this list?')">
+</form>
+
+</metal:body>
+</html>
Added: WSGIKit/trunk/examples/todo_sql/web/__init__.py
===================================================================
--- WSGIKit/trunk/examples/todo_sql/web/__init__.py 2005-04-04 02:17:38 UTC (rev 2292)
+++ WSGIKit/trunk/examples/todo_sql/web/__init__.py 2005-04-04 02:18:01 UTC (rev 2293)
@@ -0,0 +1,16 @@
+import os
+from wsgikit import wsgilib
+import sqlobject
+
+sql_set = False
+
+def urlparser_hook(environ):
+ global sql_set
+ if not environ.has_key('.base_url'):
+ environ['.base_url'] = environ['SCRIPT_NAME']
+ if not sql_set:
+ sql_set = True
+ db_uri = environ['wsgikit.config']['database']
+ sqlobject.sqlhub.processConnection = sqlobject.connectionForURI(
+ db_uri)
+
Added: WSGIKit/trunk/examples/todo_sql/web/edit_list.py
===================================================================
--- WSGIKit/trunk/examples/todo_sql/web/edit_list.py 2005-04-04 02:17:38 UTC (rev 2292)
+++ WSGIKit/trunk/examples/todo_sql/web/edit_list.py 2005-04-04 02:18:01 UTC (rev 2293)
@@ -0,0 +1,29 @@
+from todo_sql.sitepage import SitePage
+from todo_sql.db import *
+
+class edit_list(SitePage):
+
+ def setup(self):
+ self.list_id = self.request().field('id')
+ if self.list_id != 'new':
+ self.list = TodoList.get(int(self.list_id))
+ self.options.title = 'Edit list '
+
+ def actions(self):
+ return ['save', 'destroy']
+
+ def save(self):
+ desc = self.request().field('description')
+ if self.list_id == 'new':
+ self.list = TodoList(description=desc)
+ self.message('List created')
+ else:
+ self.list.description = desc
+ self.message('List updated')
+ self.sendRedirectAndEnd(self.url.view_list(id=self.list.id))
+
+ def destroy(self):
+ desc = self.list.description
+ self.list.destroySelf()
+ self.message('List %s deleted' % desc)
+ self.sendRedirectAndEnd(self.url)
Added: WSGIKit/trunk/examples/todo_sql/web/index.py
===================================================================
--- WSGIKit/trunk/examples/todo_sql/web/index.py 2005-04-04 02:17:38 UTC (rev 2292)
+++ WSGIKit/trunk/examples/todo_sql/web/index.py 2005-04-04 02:18:01 UTC (rev 2293)
@@ -0,0 +1,8 @@
+from todo_sql.sitepage import SitePage
+from todo_sql.db import *
+
+class index(SitePage):
+
+ def setup(self):
+ self.options.title = 'List of Lists'
+
Added: WSGIKit/trunk/examples/todo_sql/web/static/stylesheet.css
===================================================================
--- WSGIKit/trunk/examples/todo_sql/web/static/stylesheet.css 2005-04-04 02:17:38 UTC (rev 2292)
+++ WSGIKit/trunk/examples/todo_sql/web/static/stylesheet.css 2005-04-04 02:18:01 UTC (rev 2293)
@@ -0,0 +1,22 @@
+body {
+ font-family: Helvetica, Arial, sans-serif;
+}
+
+pre {
+ overflow: auto;
+}
+
+div.notifyMessage {
+ border: 2px solid black;
+ background-color: #007700;
+ color: #ffffff;
+}
+
+td#sidenav {
+ background-color: #eeeeee;
+}
+
+h1#header {
+ display: block;
+ background-color: #dddddd;
+}
\ No newline at end of file
Added: WSGIKit/trunk/examples/todo_sql/web/view_list.py
===================================================================
--- WSGIKit/trunk/examples/todo_sql/web/view_list.py 2005-04-04 02:17:38 UTC (rev 2292)
+++ WSGIKit/trunk/examples/todo_sql/web/view_list.py 2005-04-04 02:18:01 UTC (rev 2293)
@@ -0,0 +1,39 @@
+from todo_sql.sitepage import SitePage
+from todo_sql.db import *
+
+class view_list(SitePage):
+
+ def setup(self):
+ self.options.list = TodoList.get(int(self.request().field('id')))
+ self.options.title = 'List: %s' % self.options.list.description
+ self.options.list_items = list(self.options.list.items)
+
+ def actions(self):
+ return ['check', 'add', 'destroy']
+
+ def check(self):
+ field = self.request().field
+ for item in self.options.list.items:
+ checked = field('item_%s' % item.id, False)
+ if not checked and item.done:
+ self.message('Item %s marked not done'
+ % item.description)
+ item.done = False
+ if checked and not item.done:
+ self.message('Item %s marked done'
+ % item.description)
+ item.done = True
+ self.sendRedirectAndEnd(
+ self.url.view_list(id=self.options.list.id))
+
+ def add(self):
+ desc = self.request().field('description')
+ if not desc:
+ self.message('You must give a description')
+ else:
+ TodoItem(todo_list=self.options.list,
+ description=desc)
+ self.message('Item added')
+ self.sendRedirectAndEnd(
+ self.url.view_list(id=self.options.list.id))
+
|