status 0913.2005: looks up to date, but need to get code under test
Michal Wallace Thu, 23 May 2002 03:10:25 -0400 (Eastern Daylight Time)Usually, when we're building a web app, we want to deal with more than one type of data object, and store the data in some sort of database.
If that's the case, then one of our first goals is to figure out what sort of data objects we're going to work with, and how they relate.
A good rule of thumb is that if you have a written description of the system you want to build, and you underline all the nouns, you'll wind up with a list of the data objects you'll need.
For example, in the description of the control panel, I mentioned nouns like:
All of these can be stored as a single record in a database, so this is a good starting point. [1]
On the other hand, this is just a skeleton of a data model. Once we know what the objects are, we want to know what sort of data they'll contain, and how they relate to each other.
Let's look at email addresses as an example.
When a user adds a domain to her account, I configure the
server to accept all mail for that domain. Usually, all the
mail goes directly to her inbox. But sometimes, she wants
her mail to go to her existing email address, or to forward
certain usernames@herdomain to
outside addresses.
The way I'd handle these fields is to make the catch-all address a property of the domain, and each forwarding address is an object of its own. [2]
Here is how I might define the "Domain" and "Forward" data objects in python:
from strongbox import Strongbox, attr
class Domain(Strongbox):
ID = attr(long)
userID = attr(long)
domain = attr(str)
mailto = attr(str)
class Forward(Strongbox):
ID = attr(long)
domainID = attr(long)
virtuser = attr(str)
mailto = attr(str)
Python doesn't usually make it this easy to declare what attributes a class has. Normally, you can add just about anything to an object, and python doesn't care.
With a data model, it's nice to be able to restrict which attributes are available, and what can go in them.
This is especially important when storing objects in a relational database, because the database only has certain columns. If we try to put data into an attribute without a corresponding column, we'll lose data, so we want to make sure trying would throw an error.
The Strongbox module lets us limit an object's attributes in this way. For example, f you put the above code in an *.app file at cornerhost, and then add the line:
d = Domain(name="webappworkshop.com")
... You'll get an error.
Why? Because "name" is not a valid attribute of the "Domain" class. Change it to "domain" and it'll work fine.
Besides defining simple attributes like these, Strongbox lets you validate attributes according to more advanced python features, such as lambdas, regular expressions, and accessor methods. [3]
More importantly, though, defining your data objects in a standard form like this makes it easy to build generic tools to deal with them. For example, if you choose to store these objects in a MySQL database, you can write an class that will take a Strongbox object and a table name, and automatically generate the SQL for creating, retreiving, updating, and deleting the appropriate rows in the database. In fact, I've already done that, and I'll talk about that in an upcoming lesson.
In the next lesson, though, we'll take a break from the data objects, and actually build a simple web app!
---- Notes:[1] All the nouns work as objects except "billing history" (which would most likely be a set of "transaction" or "event" objects)
We wouldn't store a "website" in the control panel database, either, but we might store the information needed to configure the webserver to serve that site.
[2] I treat my data model as a relational database, which I can enhance by adding behaviors. Therefore, I follow the same rules of normalization (eliminating redunandcy) that one normally follows when designing a database. For a quick overview of these rules, see: http://burks.brighton.ac.uk/burks/foldoc/35/28.htm
[3] For more info on strongbox's capabilities, see the strongbox page