Idenitity using email addresses

I’m a picky programmer and I like to have things “just so”. I’m creating an app using Turbogears and it’s Identity framework, but I wanted to have people log on using their email address rather than an arbitrary username. I didn’t fancy messing around with the SOProvider myself, nor did I want to just stuff an email address into a field called username in my database (I did mention I was picky, right?).

The solution is simple, but I thought I’d share this anyway as the theory behind it is fairly powerful.

class User(SQLObject):
        email_address = UnicodeCol( length=255, alternateID=True,
                               alternateMethodName="by_email_address" )
        ....
        def _get_user_name(self):
                return self.email_address

        def _set_user_name(self, new):
                self.email_address = new

        @classmethod
        def by_user_name(self, text):
                return self.by_email_address(text)

Now, as I said, this is pretty simple at first glance but it tricks SOProvider (or anything else that accesses the user_name property) into thinking that the user_name is a real item in the database. In effect, we are giving email_address an “alias” of user_name.

You can also use this method to provide some form of action on data before it hits your database:

class Car(SQLObject):
        manufacturer = ForeignKey("Manufacturer")
        model = UnicodeCol(length=50)
        wheels = IntCol()

        def _set_manufacturer(self, name):
                try:
                       mf = Manufacturer.byName(name)
                except SQLObjectNotFound:
                        mf = Manufacturer(name=name)

                self._SO_set_manufacturer_id = mf.id

class Manufacturer(SQLObject):
        name = UnicodeCol(alternateID=True)

I wrote this code on the blog, so it’s not tested in any way, but you get the idea. You’ll be able to create manufacturers on the fly when creating or updating a Car if they’re not already available. Neat, huh?