Japanse New-Girl Monkey Network
Wishes & Reinventing the Wheel Part II
I'm not really into the wishlist thing, but I couldn't help being tempted. Really tempted. It would be so nice to have a machine with OSX, now that all my software is steadily becoming completely obsolete. On the other hand, there are almost 4 days to go on the auction and the price is already nearly AU$700. Who knows where it'll be tomorrow. Anybody wanna donate a wad of cash to me?
Well, back to the feasible wishlist -- the one where I get to pick all my own customized features of my blog. Here's a text file of my new database structure. I'm sure it's not perfectly in fourth normal form, and database design gurus everywhere can freely mock me. But I think it should work reasonably well. And I even have an unreadable ASCII diagram of the table relationships. Whee!
If anybody does look at it, they'll notice one table I haven't mentioned before: blogs_article_associations. That's because I'm still mulling that one over. I'd like a way to associate articles directly with each other (for example, if I refer back to a particular article, that maybe doesn't have a cognitive association for me as defined by projects or categories). But I think it might be something I save for the second pass of this rewrite.
So I guess that's the database, in all its unholy entirety. What next? Babble about the code?
I wrote a little data module type thing. It basically builds SQL queries for me so I don't have to keep typing "SELECT blah blah blah FROM blah WHERE blah" all the time. It also contains a little function that automatically does some stuff with the Python postgresql module I use, like format the results of a query the way I want it. It's eloquently named "data." I'm not going to include any samples of that code because it's nothing particularly revolutionary.
I also wrote a package called DBObjects. I created a base class to grab stuff from the database, slice it, dice it, update it, whatever. In the current version of ARJLog I'm just doing a lot of database calls and manipulating them by hand. It got old really fast, especially since I'm well rehearsed in the principles of OOP. But at that stage I just wanted to get something working, and I was still really low on the Python learning curve. In the new version, all of my basic weblog pieces will inherit from DatabaseObject, which does 90% of the work. This makes changing stuff much easier. So here's some of my beautiful base class (stored in __init__.py). Please excuse the crummy coding style.
class DatabaseObject:
Parameters:
Fields: List of strings, ['field1',..,'fieldn']
Links: Foreign key relationships {'linkedfield':(('ftable','fkey')...)}
IDField: Primary key (assumes only 1)
Table: string name of the table
ID: Get data from DB for this ID
Values: Data already retrieved, load these values"""
def __init__(self,Fields=[],Links={},IDField='',Table='',ID=None,Values={}):
expects either an ID from the database so it can go fetch all the rest of the
information about the object, or a dictionary of values:
{'attribute name':'attribute value'}
Otherwise it assumes you are going to insert a new object into the database."""
dictvals = {}
self.__dict__['Fields'] = Fields
self.__dict__['Links'] = Links
self.__dict__['ID_Field'] = IDField
self.__dict__['Table'] = Table
if len(Links): self.__initlinks(Links)
if len(Values): dictvals = Values
elif ID:
dictvals = data.ExecuteQuery(sel,DBNAME)
their values in the object. It also makes sure that you're not adding any
funky random fields that don't correspond with anything in the database."""
for fld in Values.keys():
relationships with other tables. It could probably use some graceful error
handling and checking. It's somewhat under development still."""
ftbls = {}
for fld in Links.keys():
for tpl in linklst:
if ftbls.has_key(ftable): ftbls[ftable].append((fkey,fld))
else: ftbls[ftable] = [(fkey,fld)]
Values = []
for fld in Fields:
documentation. What I'm doing here is making sure that you can only get
object attributes which correspond with database fields."""
if Key in self.__dict__['Fields'] or Key in self.__dict__.keys():
else: return None
I don't want anyone arbitrarily setting a row's ID. So I make sure you can't
do that here."""
if Key == self.__dict__['ID_Field']: raise AttributeError,Key + ' is read-only'
if Key in self.__dict__['Fields']:
for key in self.__dict__.keys():
say, for example, getting all the articles in a category from
blogs_article_categories."""
FKey = ''
KeyFields = self.__dict__['__ftables'][FTable]
for tpl in KeyFields:
else: return None
this object. If ID isn't null, it just doesn't do anything. And it doesn't
check to see what fields are required by the database. I might fix that."""
if getattr(self,self.ID_Field) is None:
shortfields.remove(self.__dict__['ID_Field'])
values = self.__getvalues(shortfields)
ins = data.InsertQuery(self.__dict__['Table'],shortfields,values)
oid = data.ExecuteQuery(ins,DBNAME)
sel = data.SelectQuery(self.__dict__['Table'],[],'oid = ' + str(oid))
dictvals = data.ExecuteQuery(sel,DBNAME)
self.__setvalues(dictvals)
attribute values. The object has to already exist in the database."""
if getattr(self,self.ID_Field):
shortfields.remove(self.__dict__['ID_Field'])
values = self.__getvalues(shortfields)
upd = data.UpdateQuery(self.__dict__['Table'], shortfields, values, self.__dict__['ID_Field'] + "=" + str(getattr(self,self.ID_Field)))
data.ExecuteQuery(upd,DBNAME)
Hey, this is fun. I don't even have to think up stuff to write. I just post code. No wonder TechBloggers are so prolific. Except no one's probably reading this anymore...
{ link me }