From df88f0f7a09fe888229ef1f8ce5e36253e09aab6 Mon Sep 17 00:00:00 2001 From: Miguel Grinberg Date: Sun, 16 Dec 2012 00:29:49 -0800 Subject: [PATCH] database --- app/__init__.py | 5 ++++- app/models.py | 23 ++++++++++++++++++++ config.py | 8 ++++++- db_create.py | 12 +++++++++++ db_downgrade.py | 7 +++++++ db_migrate.py | 15 +++++++++++++ db_repository/README | 4 ++++ db_repository/__init__.py | 0 db_repository/manage.py | 5 +++++ db_repository/migrate.cfg | 25 ++++++++++++++++++++++ db_repository/versions/001_migration.py | 28 +++++++++++++++++++++++++ db_repository/versions/002_migration.py | 28 +++++++++++++++++++++++++ db_repository/versions/__init__.py | 0 db_upgrade.py | 6 ++++++ 14 files changed, 164 insertions(+), 2 deletions(-) create mode 100644 app/models.py create mode 100755 db_create.py create mode 100755 db_downgrade.py create mode 100755 db_migrate.py create mode 100644 db_repository/README create mode 100644 db_repository/__init__.py create mode 100644 db_repository/manage.py create mode 100644 db_repository/migrate.cfg create mode 100644 db_repository/versions/001_migration.py create mode 100644 db_repository/versions/002_migration.py create mode 100644 db_repository/versions/__init__.py create mode 100755 db_upgrade.py diff --git a/app/__init__.py b/app/__init__.py index 963e227..67ffa87 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -1,6 +1,9 @@ from flask import Flask +from flask.ext.sqlalchemy import SQLAlchemy app = Flask(__name__) app.config.from_object('config') +db = SQLAlchemy(app) + +from app import views, models -from app import views diff --git a/app/models.py b/app/models.py new file mode 100644 index 0000000..4bf9b23 --- /dev/null +++ b/app/models.py @@ -0,0 +1,23 @@ +from app import db + +ROLE_USER = 0 +ROLE_ADMIN = 1 + +class User(db.Model): + id = db.Column(db.Integer, primary_key = True) + nickname = db.Column(db.String(64), index = True, unique = True) + email = db.Column(db.String(120), index = True, unique = True) + role = db.Column(db.SmallInteger, default = ROLE_USER) + posts = db.relationship('Post', backref = 'author', lazy = 'dynamic') + + def __repr__(self): + return '' % (self.nickname) + +class Post(db.Model): + id = db.Column(db.Integer, primary_key = True) + body = db.Column(db.String(140)) + timestamp = db.Column(db.DateTime) + user_id = db.Column(db.Integer, db.ForeignKey('user.id')) + + def __repr__(self): + return '' % (self.body) \ No newline at end of file diff --git a/config.py b/config.py index a5655eb..5aafd2a 100644 --- a/config.py +++ b/config.py @@ -1,3 +1,6 @@ +import os +basedir = os.path.abspath(os.path.dirname(__file__)) + CSRF_ENABLED = True SECRET_KEY = 'you-will-never-guess' @@ -6,4 +9,7 @@ OPENID_PROVIDERS = [ { 'name': 'Yahoo', 'url': 'https://me.yahoo.com' }, { 'name': 'AOL', 'url': 'http://openid.aol.com/' }, { 'name': 'Flickr', 'url': 'http://www.flickr.com/' }, - { 'name': 'MyOpenID', 'url': 'https://www.myopenid.com' }] \ No newline at end of file + { 'name': 'MyOpenID', 'url': 'https://www.myopenid.com' }] + +SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'app.db') +SQLALCHEMY_MIGRATE_REPO = os.path.join(basedir, 'db_repository') \ No newline at end of file diff --git a/db_create.py b/db_create.py new file mode 100755 index 0000000..f35f9bc --- /dev/null +++ b/db_create.py @@ -0,0 +1,12 @@ +#!flask/bin/python +from migrate.versioning import api +from config import SQLALCHEMY_DATABASE_URI +from config import SQLALCHEMY_MIGRATE_REPO +from app import db +import os.path +db.create_all() +if not os.path.exists(SQLALCHEMY_MIGRATE_REPO): + api.create(SQLALCHEMY_MIGRATE_REPO, 'database repository') + api.version_control(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO) +else: + api.version_control(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO, api.version(SQLALCHEMY_MIGRATE_REPO)) diff --git a/db_downgrade.py b/db_downgrade.py new file mode 100755 index 0000000..53c906a --- /dev/null +++ b/db_downgrade.py @@ -0,0 +1,7 @@ +#!flask/bin/python +from migrate.versioning import api +from config import SQLALCHEMY_DATABASE_URI +from config import SQLALCHEMY_MIGRATE_REPO +v = api.db_version(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO) +api.downgrade(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO, v - 1) +print 'Current database version: ' + str(api.db_version(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO)) diff --git a/db_migrate.py b/db_migrate.py new file mode 100755 index 0000000..8762121 --- /dev/null +++ b/db_migrate.py @@ -0,0 +1,15 @@ +#!flask/bin/python +import imp +from migrate.versioning import api +from app import db +from config import SQLALCHEMY_DATABASE_URI +from config import SQLALCHEMY_MIGRATE_REPO +migration = SQLALCHEMY_MIGRATE_REPO + '/versions/%03d_migration.py' % (api.db_version(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO) + 1) +tmp_module = imp.new_module('old_model') +old_model = api.create_model(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO) +exec old_model in tmp_module.__dict__ +script = api.make_update_script_for_model(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO, tmp_module.meta, db.metadata) +open(migration, "wt").write(script) +api.upgrade(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO) +print 'New migration saved as ' + migration +print 'Current database version: ' + str(api.db_version(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO)) diff --git a/db_repository/README b/db_repository/README new file mode 100644 index 0000000..6218f8c --- /dev/null +++ b/db_repository/README @@ -0,0 +1,4 @@ +This is a database migration repository. + +More information at +http://code.google.com/p/sqlalchemy-migrate/ diff --git a/db_repository/__init__.py b/db_repository/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/db_repository/manage.py b/db_repository/manage.py new file mode 100644 index 0000000..554f89c --- /dev/null +++ b/db_repository/manage.py @@ -0,0 +1,5 @@ +#!/usr/bin/env python +from migrate.versioning.shell import main + +if __name__ == '__main__': + main() diff --git a/db_repository/migrate.cfg b/db_repository/migrate.cfg new file mode 100644 index 0000000..60e9b5c --- /dev/null +++ b/db_repository/migrate.cfg @@ -0,0 +1,25 @@ +[db_settings] +# Used to identify which repository this database is versioned under. +# You can use the name of your project. +repository_id=database repository + +# The name of the database table used to track the schema version. +# This name shouldn't already be used by your project. +# If this is changed once a database is under version control, you'll need to +# change the table name in each database too. +version_table=migrate_version + +# When committing a change script, Migrate will attempt to generate the +# sql for all supported databases; normally, if one of them fails - probably +# because you don't have that database installed - it is ignored and the +# commit continues, perhaps ending successfully. +# Databases in this list MUST compile successfully during a commit, or the +# entire commit will fail. List the databases your application will actually +# be using to ensure your updates to that database work properly. +# This must be a list; example: ['postgres','sqlite'] +required_dbs=[] + +# When creating new change scripts, Migrate will stamp the new script with +# a version number. By default this is latest_version + 1. You can set this +# to 'true' to tell Migrate to use the UTC timestamp instead. +use_timestamp_numbering=False diff --git a/db_repository/versions/001_migration.py b/db_repository/versions/001_migration.py new file mode 100644 index 0000000..6390ab3 --- /dev/null +++ b/db_repository/versions/001_migration.py @@ -0,0 +1,28 @@ +from sqlalchemy import * +from migrate import * + + +from migrate.changeset import schema +pre_meta = MetaData() +post_meta = MetaData() +user = Table('user', post_meta, + Column('id', Integer, primary_key=True, nullable=False), + Column('nickname', String(length=64)), + Column('email', String(length=120)), + Column('role', SmallInteger, default=ColumnDefault(0)), +) + + +def upgrade(migrate_engine): + # Upgrade operations go here. Don't create your own engine; bind + # migrate_engine to your metadata + pre_meta.bind = migrate_engine + post_meta.bind = migrate_engine + post_meta.tables['user'].create() + + +def downgrade(migrate_engine): + # Operations to reverse the above upgrade go here. + pre_meta.bind = migrate_engine + post_meta.bind = migrate_engine + post_meta.tables['user'].drop() diff --git a/db_repository/versions/002_migration.py b/db_repository/versions/002_migration.py new file mode 100644 index 0000000..192d0f1 --- /dev/null +++ b/db_repository/versions/002_migration.py @@ -0,0 +1,28 @@ +from sqlalchemy import * +from migrate import * + + +from migrate.changeset import schema +pre_meta = MetaData() +post_meta = MetaData() +post = Table('post', post_meta, + Column('id', Integer, primary_key=True, nullable=False), + Column('body', String(length=140)), + Column('timestamp', DateTime), + Column('user_id', Integer), +) + + +def upgrade(migrate_engine): + # Upgrade operations go here. Don't create your own engine; bind + # migrate_engine to your metadata + pre_meta.bind = migrate_engine + post_meta.bind = migrate_engine + post_meta.tables['post'].create() + + +def downgrade(migrate_engine): + # Operations to reverse the above upgrade go here. + pre_meta.bind = migrate_engine + post_meta.bind = migrate_engine + post_meta.tables['post'].drop() diff --git a/db_repository/versions/__init__.py b/db_repository/versions/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/db_upgrade.py b/db_upgrade.py new file mode 100755 index 0000000..3aabbe4 --- /dev/null +++ b/db_upgrade.py @@ -0,0 +1,6 @@ +#!flask/bin/python +from migrate.versioning import api +from config import SQLALCHEMY_DATABASE_URI +from config import SQLALCHEMY_MIGRATE_REPO +api.upgrade(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO) +print 'Current database version: ' + str(api.db_version(SQLALCHEMY_DATABASE_URI, SQLALCHEMY_MIGRATE_REPO))