An Apology to SQLAlchemy
Before I started working with you, I became familiar with the Django and SQLObject ORM’s. They use the intuitive technique of assigning attributes to a model, like so:
fname = StringCol()
mi = StringCol(length=1, default=None)
lname = StringCol()
This is an intuitive and pleasing paradigm, and I was perfectly content until I heard some clever people say nice things about you. I enjoy working in new environments, so I took a look at you. Much to my suprise, I hated you. Quite strongly, in fact. It felt like taking a giant step backwards going from the above SQLObject code to the following:
person_table = Table(
class Person(object): pass
I recoiled. Why did it take so much more typing in SQLAlchemy to make a far less pythonic solution than that of SQLObject? I then ignored you until I realized that my SQLObject code was littered with list comprehensions instead of good, Right-Thing SQL; I gave you another shot, but I ran you through some more tests.
I realized that you could map multiple tables onto one object and one tables onto multiple objects, and quickly realized that this strange breed of polymorphism/inheritance, alien though it was, totally kicked the crap out of Django’s ORM. (Which, incidentally, still doesn’t support model inheritance.) Declaring tables and objects as one thing, though convenient, leads to sloppy and inefficient code. You made me realize that, and I thank you.
And then the neat ideas started flowing every which way – composite primary keys (why didn’t I think of that?), manual save-and-reload (crucial when just mucking about with data), backreferences (I am Ozymandias, king of kings! Look upon my massive amount of automatically updating references, and despair!), properties (less code to write = good), ActiveMapper (mmm…conciseness), and the way assign_mapper still allows me to treat tables inside objects as attributes.
I owe you an apology, SQLAlchemy. I wronged you.
Entry filed under: code.