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