1、连接


  1. app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:123456@127.0.0.1/test'
  2. app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
  3. db = SQLAlchemy(app)
  4. #SQLALCHEMY_COMMIT_ON_TEARDOWN 键,将其设为 True 时,每次请求结束后都会自动提交数据库中的变动。

2、声明模型


2.1 简单示例

  1. class User(db.Model):
  2. id = db.Column(db.Integer, primary_key=True)
  3. username = db.Column(db.String(80), unique=True)
  4. email = db.Column(db.String(120), unique=True)
  5. def __init__(self, username, email):
  6. self.username = username
  7. self.email = email
  8. def __repr__(self):
  9. return '<User %r>' % self.username
  10. #函数str() 用于将值转化为适于人阅读的形式,而repr() 转化为供解释器读取的形式
  • 用 Column 来定义一列。列名就是赋值给那个变量的名称

  • Flask-SQLAlchemy 要求每个模型都要定义主键,这一列经常命名为 id。

  • 主键用 primary_key=True 标记。可以把多个键标记为主键,此时它们作为复合主键。

  • 列的类型是 Column 的第一个参数。常用的有:Flask-SQLAlchmey - 图1

  • 常用的列选项有:Flask-SQLAlchmey - 图2

2.2 一对多(one-to-many)关系

  • 关系使用 relationship() 函数表示。然而外键必须用类 sqlalchemy.schema.ForeignKey 来单独声明:
  1. class Person(db.Model):
  2. id = db.Column(db.Integer, primary_key=True)
  3. name = db.Column(db.String(50))
  4. addresses = db.relationship('Address', backref='person',
  5. lazy='dynamic')
  6. class Address(db.Model):
  7. id = db.Column(db.Integer, primary_key=True)
  8. email = db.Column(db.String(50))
  9. person_id = db.Column(db.Integer, db.ForeignKey('person.id'))11111111
  • db.relationship()让它指向 Address 类并加载多个地址

  • backref 是一个在 Address 类上声明新属性的简单方法。您也可以使用 my_address.person 来获取使用该地址(address)的人(person)。lazy 决定了 SQLAlchemy 什么时候从数据库中加载数据:

    • ‘select’ (默认值) 就是说 SQLAlchemy 会使用一个标准的 select 语句必要时一次加载数据。

    • ‘joined’ 告诉 SQLAlchemy 使用 JOIN 语句作为父级在同一查询中来加载关系。

    • ‘subquery’ 类似 ‘joined’ ,但是 SQLAlchemy 会使用子查询。

    • ‘dynamic’ 在有多条数据的时候是特别有用的。不是直接加载这些数据,SQLAlchemy 会返回一个查询对象,在加载数据前您可以过滤(提取)它们。

  • 常用的关系选项
    Flask-SQLAlchmey - 图3

  • 如何为反向引用(backrefs)定义惰性(lazy)状态?使用 backref() 函数:
  1. class User(db.Model):
  2. id = db.Column(db.Integer, primary_key=True)
  3. name = db.Column(db.String(50))
  4. addresses = db.relationship('Address',
  5. backref=db.backref('person', lazy='joined'), lazy='dynamic')

2.3 多对多(many-to-many)关系

  • 想要用多对多关系,需要定义一个用于关系的辅助表。对于这个辅助表, 强烈建议不使用模型,而是采用一个实际的表:
  1. tags = db.Table('tags',
  2. db.Column('tag_id', db.Integer, db.ForeignKey('tag.id')),
  3. db.Column('page_id', db.Integer, db.ForeignKey('page.id'))
  4. )
  5. class Page(db.Model):
  6. id = db.Column(db.Integer, primary_key=True)
  7. tags = db.relationship('Tag', secondary=tags,
  8. backref=db.backref('pages', lazy='dynamic'))
  9. class Tag(db.Model):
  10. id = db.Column(db.Integer, primary_key=True)
  • 这里我们配置 Page.tags 加载后作为标签的列表,因为我们并不期望每页出现太多的标签。而每个 tag 的页面列表( Tag.pages)是一个动态的反向引用。 正如上面提到的,这意味着您会得到一个可以发起 select 的查询对象。

3、数据库操作


3.1 创建表

  1. >>> db.drop_all()
  2. #根据模型类创建数据库表
  3. >>> db.create_all()
  4. #删除数据库表

3.2 插入行

  1. 下面这段代码创建了一些角色和用户:
  2. >>> from hello import Role, User
  3. >>> admin_role = Role(name='Admin')
  4. >>> mod_role = Role(name='Moderator')
  5. >>> user_role = Role(name='User')
  6. >>> user_john = User(username='john', role=admin_role)
  7. >>> user_susan = User(username='susan', role=user_role)
  8. >>> user_david = User(username='david', role=user_role)
  9. Flask-SQLAlchemy 中,会话由 db.session 表示。准备把对象写入数据库之前,先要将其添加到会话中:
  10. >>> db.session.add(admin_role)
  11. >>> db.session.add(mod_role)
  12. >>> db.session.add(user_role)
  13. >>> db.session.add(user_john)
  14. >>> db.session.add(user_susan)
  15. >>> db.session.add(user_david)
  16. 或者简写成:
  17. >>> db.session.add_all([admin_role, mod_role, user_role, user_john, user_susan, user_david])
  18. 为了把对象写入数据库,要调用 commit() 方法提交会话:
  19. >>> db.session.commit()

3.3 修改行

  1. 下面这个例子把 "Admin" 角色重命名为 "Administrator":
  2. >>> admin_role.name = 'Administrator'
  3. >>> db.session.add(admin_role)
  4. >>> db.session.commit()

3.4 删除行

  1. 下面这个例子把 "Moderator" 角色从数据库中删除:
  2. >>> db.session.delete(mod_role)
  3. >>> db.session.commit()

3.5 查询行

  • 最基本的模型查询是取回对应表中的所有记录:
  1. >>> Role.query.all()
  2. [<Role u'Administrator'>, <Role u'User'>]
  3. >>> User.query.all()
  4. [<User u'john'>, <User u'susan'>, <User u'david'>]
  • 查找角色为”User”的所有用户:
  1. >>> User.query.filter_by(role=user_role).all() [<User u'susan'>, <User u'david'>]
  • 加载名为”User”的用户角色:
  1. >>> user_role = Role.query.filter_by(name='User').first()

filter_by()等过滤器在query对象上调用,返回一个更精确的query对象。

  • 常用过滤器有:

在查询上应用指定的过滤器后,通过调用all()执行查询,以列表的形式返回结果。

  • 常用查询执行函数有:Flask-SQLAlchmey - 图4

3、数据库操作


  1. @app.route('/user/<username>')
  2. def show_user(username):
  3. user = User.query.filter_by(username=username).first_or_404()
  4. return render_template('show_user.html', user=user)

对于不存在的条目返回一个 404 错误是非常方便的。因为这是一个很常见的问题,Flask-SQLAlchemy 为了解决这个问题提供了一个帮助函数。可以使用 get_or_404() 来代替 get(),使用 first_or_404() 来代替 first()。这样会抛出一个 404 错误,而不是返回 None