UDN-企业互联网技术人气社区

板块导航

浏览  : 1014
回复  : 0

[讨论交流] 在 Flask 中使用 SQLAlchemy

[复制链接]
cat77的头像 楼主
发表于 2016-5-19 14:41:18 | 显示全部楼层 |阅读模式
本帖最后由 cat77 于 2016-5-19 14:44 编辑

  许多人喜欢使用 SQLAlchemy 来访问数据库。建议在你的 Flask 应用中使用包来代替 模块,并把模型放入一个独立的模块中(参见 大型应用 )。虽然这 不是必须的,但是很有用。

  有四种 SQLAlchemy 的常用方法,下面一一道来:

  Flask-SQLAlchemy 扩展

  因为 SQLAlchemy 是一个常用的数据库抽象层,并且需要一定的配置才能使用,因此我们 为你做了一个处理 SQLAlchemy 的扩展。如果你需要快速的开始使用 SQLAlchemy ,那么 推荐你使用这个扩展。

  你可以从 PyPI 下载 Flask-SQLAlchemy

  声明

  SQLAlchemy 中的声明扩展是使用 SQLAlchemy 的最新方法,它允许你像 Django 一样, 在一个地方定义表和模型然后到处使用。除了以下内容,我建议你阅读 声明 的官方 文档。

  以下是示例 database.py 模块:
  1. from sqlalchemy import create_engine
  2. from sqlalchemy.orm import scoped_session, sessionmaker
  3. from sqlalchemy.ext.declarative import declarative_base

  4. engine = create_engine('sqlite:////tmp/test.db', convert_unicode=True)
  5. db_session = scoped_session(sessionmaker(autocommit=False,
  6.                                          autoflush=False,
  7.                                          bind=engine))
  8. Base = declarative_base()
  9. Base.query = db_session.query_property()

  10. def init_db():
  11.     # 在这里导入定义模型所需要的所有模块,这样它们就会正确的注册在
  12.     # 元数据上。否则你就必须在调用 init_db() 之前导入它们。
  13.     import yourapplication.models
  14.     Base.metadata.create_all(bind=engine)
复制代码

  要定义模型的话,只要继承上面创建的 Base 类就可以了。你可能会奇怪这里为什么 不用理会线程(就像我们在 SQLite3 的例子中一样使用 g 对象)。 原因是 SQLAlchemy 已经用 scoped_session 为我们做好了此 类工作。

  如果要在应用中以声明方式使用 SQLAlchemy ,那么只要把下列代码加入应用模块就可以 了。 Flask 会自动在请求结束时或者应用关闭时删除数据库会话:
  1. from yourapplication.database import db_session

  2. @app.teardown_appcontext
  3. def shutdown_session(exception=None):
  4.     db_session.remove()
复制代码

  以下是一个示例模型(放入 models.py 中):
  1. from sqlalchemy import Column, Integer, String
  2. from yourapplication.database import Base

  3. class User(Base):
  4.     __tablename__ = 'users'
  5.     id = Column(Integer, primary_key=True)
  6.     name = Column(String(50), unique=True)
  7.     email = Column(String(120), unique=True)

  8.     def __init__(self, name=None, email=None):
  9.         self.name = name
  10.         self.email = email

  11.     def __repr__(self):
  12.         return '<User %r>' % (self.name)
复制代码

  可以使用 init_db 函数来创建数据库:
  1. >>> from yourapplication.database import init_db
  2. >>> init_db()
复制代码

  在数据库中插入条目示例:
  1. >>> from yourapplication.database import db_session
  2. >>> from yourapplication.models import User
  3. >>> u = User('admin', 'admin@localhost')
  4. >>> db_session.add(u)
  5. >>> db_session.commit()
复制代码

  查询很简单:
  1. >>> User.query.all()
  2. [<User u'admin'>]
  3. >>> User.query.filter(User.name == 'admin').first()
  4. <User u'admin'>
复制代码

  人工对象关系映射

  人工对象关系映射相较于上面的声明方式有优点也有缺点。主要区别是人工对象关系映射 分别定义表和类并映射它们。这种方式更灵活,但是要多些代码。通常,这种方式与声明 方式一样运行,因此请确保把你的应用在包中分为多个模块。

  示例 database.py 模块:
  1. from sqlalchemy import create_engine, MetaData
  2. from sqlalchemy.orm import scoped_session, sessionmaker

  3. engine = create_engine('sqlite:////tmp/test.db', convert_unicode=True)
  4. metadata = MetaData()
  5. db_session = scoped_session(sessionmaker(autocommit=False,
  6.                                          autoflush=False,
  7.                                          bind=engine))
  8. def init_db():
  9.     metadata.create_all(bind=engine)
复制代码

  就像声明方法一样,你需要在请求后或者应用环境解散后关闭会话。把以下代码放入你的 应用模块:

  1. from yourapplication.database import db_session

  2. @app.teardown_appcontext
  3. def shutdown_session(exception=None):
  4.     db_session.remove()
复制代码

  以下是一个示例表和模型(放入 models.py 中):
  1. from sqlalchemy import Table, Column, Integer, String
  2. from sqlalchemy.orm import mapper
  3. from yourapplication.database import metadata, db_session

  4. class User(object):
  5.     query = db_session.query_property()

  6.     def __init__(self, name=None, email=None):
  7.         self.name = name
  8.         self.email = email

  9.     def __repr__(self):
  10.         return '<User %r>' % (self.name)

  11. users = Table('users', metadata,
  12.     Column('id', Integer, primary_key=True),
  13.     Column('name', String(50), unique=True),
  14.     Column('email', String(120), unique=True)
  15. )
  16. mapper(User, users)
复制代码

  查询和插入与声明方式的一样。

  SQL 抽象层

  如果你只需要使用数据库系统(和 SQL )抽象层,那么基本上只要使用引擎:
  1. from sqlalchemy import create_engine, MetaData

  2. engine = create_engine('sqlite:////tmp/test.db', convert_unicode=True)
  3. metadata = MetaData(bind=engine)
复制代码

  然后你要么像前文中一样在代码中声明表,要么自动载入它们:
  1. users = Table('users', metadata, autoload=True)
复制代码

  可以使用 insert 方法插入数据。为了使用事务,我们必须先得到一个连接:
  1. >>> con = engine.connect()
  2. >>> con.execute(users.insert(), name='admin', email='admin@localhost')
复制代码

  SQLAlchemy 会自动提交。

  可以直接使用引擎或连接来查询数据库:
  1. >>> users.select(users.c.id == 1).execute().first()
  2. (1, u'admin', u'admin@localhost')
复制代码

  查询结果也是类字典元组:
  1. >>> r = users.select(users.c.id == 1).execute().first()
  2. >>> r['name']
  3. u'admin'
复制代码

  你也可以把 SQL 语句作为字符串传递给 execute() 方法:
  1. >>> engine.execute('select * from users where id = :1', [1]).first()
  2. (1, u'admin', u'admin@localhost')
复制代码

相关帖子

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关于我们
联系我们
  • 电话:010-86393388
  • 邮件:udn@yonyou.com
  • 地址:北京市海淀区北清路68号
移动客户端下载
关注我们
  • 微信公众号:yonyouudn
  • 扫描右侧二维码关注我们
  • 专注企业互联网的技术社区
版权所有:用友网络科技股份有限公司82041 京ICP备05007539号-11 京公网网备安1101080209224 Powered by Discuz!
快速回复 返回列表 返回顶部