Cedar Rapids Online
a web application by Trevis Rothwell

Quick Links
Background Information
Much of what I know about building web applications I learned from Philip Greenspun's instructional materials. To execute on what I learned, I decided to build an online learning community website for residents of Cedar Rapids, Iowa. I originally built it using Python and PostgreSQL, running directly on top of the mod_python Apache module. Unfortunately, either there was very little interest on the web for a Cedar Rapids online learning community, or I did a woeful job of marketing my project. Maybe a little of both. In any event, after it became clear that the vast majority of registered users were Russian spammers, I shut the site down.
However, even if the site was not a commercial success, it was still an example of the kind of work I can do, so I eventually decided to dust it off, polish it up, and unleash it as part of my project portfolio. I spent about a week of evenings recoding the application to run in the CherryPy web framework, and released the source code under the GNU Affero GPL. It could still stand some code refactoring and other miscellaneous improvements, but I'm not really interested in running it as a real user-facing website right now, and have mostly moved on to other projects for the time being.
The remainder of this document explains the software architecture and some design decisions from the point of view of getting ready for real users.
Design Goals
This project is a traditional online learning community website, with the target audience of residents and potential future residents of Cedar Rapids, Iowa. The key features are:
- User accounts and authentication.
- Article documents, with optional user comments.
- Discussion forums, as user-generated content.
- Event calendar, as user-generated content.
Apart from building the software, this project also requires magnet content in the form of articles (ideally with some pertinent photography).
Implementation
The Big Picture
- The web site is served simply by the built-in CherryPy web server. If this ever proves unable to handle the user load, the CherryPy documentation includes suggestions for other serving options.
- The data is stored in a half-dozen PostgreSQL tables.
- The web pages are generated using Python scripts built with the CherryPy web library and the PyGreSQL database library. No HTML templating language is used, as most of the HTML content is generated from data in the database, and I have no problem writing relatively small amounts of HTML directly in Python.
The User Interface
- Index Page
The main index page includes an overview text describing the purpose of the website, and provides links to the core functionality through a menu at the top of the page. (This menu is also present on the other pages.) Without logging in, the user can view the article pages, the discussion forum, and the event calendar, but cannot contribute any information to the site. - Register Page
The user registration page lets users create a new account on the site. Users must provide a name (which will be displayed on most content they create on the site), an email address (semi-validated through regular expressions), and a password. They may optionally provide the URL of their own website. Based on past experience, full email validation, by way of (say) sending a site-generated password to the user's email account can be a hindrance for some users. While the site is new and extremely eager to attract as many new users as possible, this hurdle is not being presented. As the site grows, it may be optimal to require full email address validation.
Prior to a successful registration, the system verifies that the provided email address is not already in use, as email addresses serve as the user's login ID, and as such must be unique. - Login Page
Registered users can log in by providing their email address and password. - Articles
The main articles page is used to display an index of magnet content articles. The article index is itself an article named "map"; going to "/articles/" presents the same content as going to "/articles/map".
The articles themselves are accessible by passing the name (or, more precisely, the "slug") of the article to the "/articles/" page. For example, an article with the slug "eating-out" would be viewable at the URL "/articles/eating-out". Each article can be optionally set to allow user comments or disallow them; users must be logged in to post comments.
Note also that the main index page ("/") is an article as well, named "welcome". This is slightly non-sensical, but easily allows the main index to be editable from the articles admin interface, rather than offering a separate interface just for the index. - Discussions
The discussions page displays a listing of user-generated discussion threads, in chronologically-descending order. Like the articles page, each discussion thread is accessible as a sub-URL: "/discussions/" shows the index, and "/discussions/42" shows discussion thread #42. (Since articles are generated only by admin users, and there will ostensibly be fewer articles than discussions, articles are identified by a memorable slug name, while discussions are identified by number. A slug could be generated based on discussion subject, if more SEO-friendly URLs are desired.)
Logged-in users can start new discussions from the index, and add replies to existing threads from that thread's page. Nested threading is not implemented, in the hopes that discussions will stay on topic. - Events
The events page is very similar to the discussions page. Logged-in users can create new event listings; the main events index shows a listing of events in chronological order (with headers automatically inserted to separate months and years), and individual event details can be viewed at, e.g., "/events/42". No comments are allowed for events. - Admin Pages
The admin pages are restricted to logged-in users at the admin level (2 or higher, though presently there is no distinction for any user level above 2). There are admin pages to create and edit articles; delete comments; delete discussions; delete events. Throughout the site, if the user is an admin, there are links attached to user-generated content to go to page to delete the specified content. For example, for every discussion and reply, there will be a link to delete it. If a discussion is deleted, all replies are also deleted. If a reply is deleted, only that particular reply is deleted.
Data Model
There are five tables in the data model:
- users
- articles
- discussions
- discussion_categories
- events
Article replies are stored as articles with a non-null "refers_to" field pointing to the parent article. Discussion replies are stored with a non-null "refers_to" field pointing to the parent discussion. The discussion categories table is currently unused; when an online community is young, it's better to not segregate users into discussion categories, but rather keep all discussions together so people can find each other. As the community grows, discussion categories may be implemented.
The SQL tables are written in PostgreSQL format, and are viewable (and documented in more detail) in the code repository.
Future Directions
The existing design should be a fairly robust online learning community system. This is not a research project; online communities have existed since the mid-1990's, and much has been tried and either proven successful or failed. Any changes that need to be made in this particular online community will have to be determined based on usage.
License
The software is licensed under the GNU Affero GPL.
References
tjr@acm.org