The site is hosted on a Virtual Private Server (VPS), using the Nginx web server and Django framework.
|Host||VPS on Linode.|
|OS||Ubuntu 11.04 server.|
Nginx is the front-facing web server. It fields requests, serves static files, and hands everything else off to uWSGI. uWSGI runs a python process that in turn runs Django. Django dynamically creates the pages from data stored in the PostgreSQL database.
The application is loosely based on the CMS example in Python Web Development with Django. In that application there are two models, Story and Category. A page is built on a story, and a story can have one category (tag).
I started with that design and expanded it.
Pages are built on the Article (Story) model. A Django model is a Python class, and Django's ORM translates that into a database table whose rows store data for objects of that class. A large number of generic and model-specific query functions are also generated, for programming convenience.
Articles can have zero or many Tags (Category).
Articles also have a few extra fields useful to this site, including a List field. The List field holds Articles, which can be used directly, or in turn hold their own lists of Articles.
Example: the lists of industries and technologies associated with each job on the Resume page is an example of Articles using lists of lists. A job has two items on its List, an Industries Article whose list in turns holds a list of industries for that job, and a Technologies Article whose list holds a list of technologies for that job.
Article(JobX) +---->List +---->Article(JobX Industries) | +---->List: Article(IdustryA), Article(IndustryB), ... +---->Article(JobX Technologies) +---->List: Article(TechL), Article(TechM), ...
So the site is built with Articles and lists of Articles. It's Articles, all the way down.
This is flexible, but it's also brittle as the schema is partly defined in the code. When I come back to it in six months a little wtf bubble will probably pop in my brain.
Each article has two text fields, Content and Teaser. Both of these accept restructured text markup, which is then converted to HTML when the Article is saved.
URL and Page Design
With a few exceptions, each page's URL looks like this:
There should always be something behind a URL like:
so that if you follow the URL hierarchy up from a page, you don't get an error.
For example, http://justaaron.com/tag/gig/ is the page that shows all pages tagged with Gig.
http://justaaron.com/tag/, then, is a list of all tags.
A displayed page can be built with text contained in that page's Article, or with data from a number of different Articles, or a combination of the two; this is all pulled together using Django's view and template system. For example, there is no Article object for http://justaaron.com/tag/, but the Resume page is built with some text from the Resume Article object and from data from job, technology and industry Articles.
To use the Resume/Job/Technology example again, the Resume page is built like this:
Resume Article object Resume Article Title field Resume Article Text field [JobX section on the Resume page] JobX Article Title field JobX Article Role field JobX Article From/To dates JobX Article Location field JobX Article Industry List -> Industry Article Title field, ... JobX Article Technology List -> Technology Article Title field, ... JobX Article Teaser field (job description in this case) [JobY section on the Resume page] [JobZ section on the Resume page] ...
Many pages on the site just have a title and a few other fields filled in, with no main content, so that they can be used by the Resume page. Those pages are waiting for me to supply their main content and so create a page that's interesting by itself.
You can see a list of all public pages on the site at Pages, divided into a list of pages with content, and a list of pages without content (other than described above for JobX, for example).
Updated Nov. 25, 2011, 2:17 a.m.