Package: mig
mig - SQLAlchemy migrationsmig ([M]ediaGoblin [i]s [G]reat!) was first written byChristopher Allan WebberforGNU MediaGoblin.Since then,Joar Wandborghas extracted the essentials
of the functionality from MediaGoblin and into a separate package which’s README
you are currently reading.Init migrationsEither runmig.run(engine, name, models, migrations)or add themig.models.MigrationDatatable manually.NoteIf your database is already populated and there are no migration version rows in the MigrationData table,mig.run()will fail.If you already have a populated database you’ll need to create aMigrationData(name='migrations_handle',version=0)row for your migrations in the MigrationData table, otherwise mig will try to initiate the database.Example setupCreate migrationfrommigimportRegisterMigrationfromsqlalchemyimportMetaData,Table,Column,Integer,Unicode,DateTime,\ForeignKeyMIGRATIONS={}@RegisterMigration(1,MIGRATIONS)defcreate_site_table(db_conn):metadata=MetaData(bind=db_conn.bind)user_table=Table('user',metadata,autoload=True,autoload_with=db_conn.bind)site_table=Table('site',metadata,Column('id',Integer,primary_key=True),Column('domain',Unicode),Column('owner_id',Integer,ForeignKey(user_table.columns['id'])))site_table.create()db_conn.commit()@RegisterMigration(2,MIGRATIONS)defitem_add_site_id(db_conn):metadata=MetaData(bind=db_conn.bind)item_table=Table('item',metadata,autoload=True)site_table=Table('site',metadata,autoload=True)site_id_col=Column('site_id',Integer,ForeignKey(site_table.columns['id']))site_id_col.create(item_table)db_conn.commit()Register modelsimportbcryptfromdatetimeimportdatetimefrommigrateimportchangesetfromtalkatvimportdbclassUser(db.Model):id=db.Column(db.Integer,primary_key=True)username=db.Column(db.String(60),unique=True)email=db.Column(db.String(255),unique=True)password=db.Column(db.String(60))def__init__(self,username,email,password=None,openid=None):self.username=usernameself.email=emailifpassword:self.set_password(password)ifopenid:self.openid=openiddef__repr__(self):return'<User{0}>'.format(self.username)defset_password(self,password):self.password=bcrypt.hashpw(password,bcrypt.gensalt())defcheck_password(self,password):returnbcrypt.hashpw(password,self.password)==self.passwordclassOpenID(db.Model):id=db.Column(db.Integer,primary_key=True)url=db.Column(db.String())created=db.Column(db.DateTime)user_id=db.Column(db.Integer,db.ForeignKey('user.id'))user=db.relationship('User',backref=db.backref('openids',lazy='dynamic'))def__init__(self,user,url):self.created=datetime.utcnow()self.user=userself.url=urlclassItem(db.Model):id=db.Column(db.Integer,primary_key=True)title=db.Column(db.String())url=db.Column(db.String(),unique=True)created=db.Column(db.DateTime)site_id=db.Column(db.Integer,db.ForeignKey('site.id'))site=db.relationship('Site',backref=db.backref('items',lazy='dynamic'))def__init__(self,url,title,site=None):ifsite:self.site=siteself.title=titleself.url=urlself.created=datetime.utcnow()def__repr__(self):return'<Item{0}({1})>'.format(self.url,self.site.owner.usernameifself.siteelseNone)defas_dict(self):me={'id':self.id,'title':self.title,'url':self.url,'created':self.created.isoformat()}ifself.site:me.update({'owner':self.site.owner.id})returnmeclassSite(db.Model):id=db.Column(db.Integer,primary_key=True)created=db.Column(db.DateTime)domain=db.Column(db.String)owner_id=db.Column(db.Integer,db.ForeignKey('user.id'))owner=db.relationship('User',backref=db.backref('sites',lazy='dynamic'))def__init__(self,owner,domain):self.owner=ownerself.domain=domainself.created=datetime.utcnow()def__repr__(self):return'<Site{0}({1})>'.format(self.domain,self.owner.username)classComment(db.Model):id=db.Column(db.Integer,primary_key=True)created=db.Column(db.DateTime)text=db.Column(db.String())item_id=db.Column(db.Integer,db.ForeignKey('item.id'))item=db.relationship('Item',backref=db.backref('comments',lazy='dynamic'))user_id=db.Column(db.Integer,db.ForeignKey('user.id'))user=db.relationship('User',backref=db.backref('comments',lazy='dynamic'))def__init__(self,item,user,text):self.item=itemself.user=userself.text=textself.created=datetime.utcnow()def__repr__(self):return'<Comment{0}({1})>'.format(self.text[:25]+('...'iflen(self.text)>25else''),self.user.username)defas_dict(self):me={'id':self.id,'item':self.item.id,'user_id':self.user.id,'username':self.user.username,'text':self.text,'created':self.created.isoformat()}returnmeMODELS=[User,Comment,Item,OpenID,Site]Run migrationsfrommigimportrunfrommig.modelsimportMigrationDatafromyourappimportdbfromyourapp.modelsimportMODELSfromyourapp.migrationsimportMIGRATIONSdefcheck_or_create_mig_data():ifnotdb.engine.dialect.has_table(db.session,'mig__data'):# Create migration tableMigrationData.__table__.create(db.engine)# Create the first migration, so that mig doesn't init.migration=MigrationData(name=u'__main__',version=0)db.session.add(migration)db.session.commit()if__name__=='__main__':ifdb.engine.dialect.has_table(db.session,'user'):# The DB is already populated, check if migrations are active,# otherwise create the migration data tablecheck_or_create_mig_data()run(db.engine,u'__main__',MODELS,MIGRATIONS)