日課書

编程100小时挑战

Flask中使用SQLAlchemy

在Web程序中一般采用数据库来保存数据,需要时再向数据库发出查询或者修改。使用的数据库一般为关系型数据库。关系型数据库把数据存储在表中,表模拟程序中不同«»的实体。表的列定义了实体的数据属性,而行则是实体的各条数据项。表和表之间的行可以通过外键进行连接。在Flask中,我们可以才用关系型数据框架SQLAlchemy来作为ORM提升开发效率。

1. 配置数据库

1
2
3
4
5
6
7
8
9
10
from flask_sqlalchemy import SQLAlchemy

basedir = os.path.abspath(os.path.dirname(__file__))

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = \
'sqlite:///' + os.path.join(basedir, 'data.sqlite')
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True

db = SQLAlchemy(app)

2. 定义模型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Role(db.Model):
__tablename__ = 'roles'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), unique=True)

def __repr__(self):
return '<Role %r>' % self.name

class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), unique=True, index=True)

def __repr__(self):
return '<User %r>' % self.username

3. 关系

1
2
3
4
5
6
7
class Role(db.Model):
# ...
users = db.relationship('User', backref='role')

class User(db.Model):
# ...
role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))

4. 数据库操作

  • 创建表
1
2
3
4
$ python hello.py shell
>>> from hello import db
>>> db.drop_all()
>>> db.create_all()
  • 插入行
1
2
3
4
5
6
7
8
9
10
>>> from hello import Role, User
>>> admin_role = Role(name='Admin')
>>> mod_role = Role(name='Moderator')
>>> user_role = Role(name='User')
>>> user_john = User(username='john', role=admin_role)

>>> db.session.add_all([admin_role, mod_role, user_role, user_john])
>>> db.session.commit()

>>> db.session.rollback()
  • 修改行
1
2
3
>>> admin_role = 'Administrator'
>>> db.session.add(admin_role)
>>> db.session.commit()
  • 删除行
1
2
>>> db.session.delete(mod_role)
>>> db.session.commit()
  • 查询
1
2
3
4
5
6
7
8
9
10
11
>>> Role.query.all()
>>> User.query.all()

>>> User.query.filter_by(role=user_role).all()
>>> str(User.query.filter_by(role=user_role))

>>> user_role = Role.query.filter_by(name='User').first()

# lazy="dynamic"
>>> user_role.users.order_by(User.name).all()
>>> user_role.users.count()

5. 集成Python shell

1
$ pip install flask-script
1
2
3
4
5
6
7
from flask.ext.script import Shell, Manager

def make_shell_context():
return dict(app=app, db=db, User=User, Role=Role)

manager = Manager(app)
manager.add_command("shell", Shell(make_context=make_shell_context))
1
2
3
$ python hello.py shell
>>> app
>>> db

6. 使用Flask-Migrate实现数据库迁移

1
$ pip install Flask-Migrate
  • 创建迁移仓库
1
2
3
4
from flask.ext.migrate import Migrate, MigrateCommand
# ...
migrate = Migrate(app, db)
manager.add_command('db', MigrateCommand)
1
$ python hello.py db init
  • 创建迁移脚本
1
$ python hello.py db migrate -m "initial migrate"
  • 更新数据库
1
2
$ python hello.py db upgrade
# downgrade