Flask-RESTful——SQLAlchemy

一、Flask-SQLAlchemy

Flask-SQLAlchemy 使用起来非常有趣,对于基本应用十分容易使用,并且对于大型项目易于扩展。有关完整的指南,请参阅 SQLAlchemy 的 API 文档。

1、创建一个最小的应用

常见情况下对于只有一个 Flask 应用,所有您需要做的事情就是创建 Flask 应用,选择加载配置接着创建 SQLAlchemy 对象时候把 Flask 应用传递给它作为参数。
一旦创建,这个对象就包含 sqlalchemy 和 sqlalchemy.orm 中的所有函数和助手。此外它还提供一个名为 Model 的类,用于作为声明模型时的 delarative 基类:

连接配置
# settings.py
DIALECT = 'mysql'
DRIVER = 'pymysql'
USERNAME = 'root'
PASSWORD = '808069'
HOST = '127.0.0.1'
PORT = '3306'
DATABASE = 'cms'

SQLALCHEMY_DATABASE_URI = '{}+{}://{}:{}@{}:{}/{}?charset=utf8'.format(
    DIALECT,DRIVER,USERNAME,PASSWORD,HOST,PORT,DATABASE
)
SQLALCHEMY_COMMIT_ON_TEARDOWN = True
SQLALCHEMY_TRACK_MODIFICATIONS = True
创建连接
# manage.py 
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy(app)
建表
# models.py
from manage import db
 
class User(db.Model):
    __tablename__ = 'user'
    id = db.Column(db.INTEGER,primary_key=True)
    username = db.Column(db.String(80),unique=True)
    password = db.Column(db.String(80),nullable=False)
 
class CodeCountRecord(db.Model):
    __tablename = 'codecountrecord'
    id = db.Column(db.INTEGER,primary_key=True)
    count = db.Column(db.INTEGER)
    data = db.Column(db.DATE)
    user = db.Column(db.ForeignKey('user.id'))
 
 
db.create_all()
2、数据的CURD
在查询数据之前我们必须先插入数据。
您的所有模型都应该有一个构造函数,如果您 忘记了,请确保加上一个。

只有您自己使用这些构造函数而 SQLAlchemy 在内部不会使用它, 
所以如何定义这些构造函数完全取决与您。

向数据库插入数据分为三个步骤:
			创建 Python 对象
			把它添加到会话 :这里的会话不是 Flask 的会话,而是 Flask-SQLAlchemy 的会话。
										  它本质上是一个 数据库事务的加强版本。
			提交会话

把对象添加到会话之前, SQLAlchemy 基本不考虑把它加到事务中。
这是好事,因为您仍然可以放弃更改。

调用 add() 函数会添加对象。
它会发出一个 INSERT 语句给数据库,但是由于事务仍然没有提交,您不会立即得到返回的 ID 。
如果您提交,您的用户会有一个 ID:

from cms.models import User
from manage import db
 
def create_user():
    # 创建一个新用户对象
    user = User()
    user.username = 'fuyong'
    user.password = '123'
 
    # 将新创建的用户添加到数据库会话中
    db.session.add(user)
    # 将数据库会话中的变动提交到数据库中, 记住, 如果不 commit, 数据库中是没有变化的.
    db.session.commit()
 
create_user()
def delete_user():
    # 获取用户对象
    user = User.query.filter_by(id=1).first()
 
    # 删除用户
    db.session.delete(user)
 
    #提交数据库会话
    db.session.commit()
 
delete_user()
def update_user():
    # 获取用户对象
    user = User.query.filter_by(id=2).first()
 
    # 修改用户
    user.password = '123567'
 
    #提交数据库会话
    db.session.commit()
 
update_user()

Flask-SQLAlchemy 在您的 Model 类上提供了 query 属性。
当您访问它时,您会得到一个新的所有记录的查询对象。
在使用 all() 或者 first() 发起查询之前可以使用方法 filter() 来过滤记录。
如果您想要用主键查询的话,也可以使用 get()。

def select_user():
    # 查询所有用户
    users_list = User.query.all()
 
    # 查询用户名称为 fuyong 的第一个用户, 并返回用户实例, 
    # 因为之前定义数据库的时候定义用户名称唯一, 所以数据库中用户名称为 test 的应该只有一个.
    user = User.query.filter_by(username='fuyong').first()
    # or
    user = User.query.filter(User.username == 'fuyong').first()
 
    # 模糊查询, 查找用户名以abc 结尾的所有用户
    users_list = User.query.filter(User.username.endsWith('g')).all()
 
    # 查询用户名不是 fuyong 的第一个用户
    user = User.query.filter(User.username != 'fuyong').first()

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

循环导入问题

解决办法就是另外创建一个ext.py文件,专门用来创建db,代码如下:

from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
db.init_app(app)
3、表间关系

SQLAlchemy 连接到关系型数据库,关系型数据最擅长的东西就是关系。

一对一关系

如果您想要一对一关系,您可以把 uselist=False 传给 relationship() 。

class Person(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(50))
    addresses = db.relationship('Address', backref='person',
                                lazy='dynamic',uselist=False)
# lazy 决定了 SQLAlchemy 什么时候从数据库中加载数据:
	# 'select' (默认值) 就是说 SQLAlchemy 会使用一个标准的 select 语句必要时一次加载数据。
	# 'joined' 告诉 SQLAlchemy 使用 JOIN 语句作为父级在同一查询中来加载关系
	# 'subquery' 类似 'joined' ,但是 SQLAlchemy 会使用子查询。
	# 'dynamic' 在有多条数据的时候是特别有用的。不是直接加载这些数据,
		# SQLAlchemy 会返回一个查询对象,在加载数据前您可以过滤(提取)它们。
		
# backref 是一个在 Address 类上声明新属性的简单方法。

class Address(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(50))
    person_id = db.Column(db.Integer, db.ForeignKey('person.id'))

问:您如何为反向引用(backrefs)定义惰性(lazy)状态?
答:使用 backref() 函数:

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(50))
    addresses = db.relationship('Address',
        backref=db.backref('person', lazy='joined'), lazy='dynamic')
一对多关系
class Person(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(50))
    addresses = db.relationship('Address', backref='person',
                                lazy='dynamic')

class Address(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(50))
    person_id = db.Column(db.Integer, db.ForeignKey('person.id'))
多对多关系

如果您想要用多对多关系,您需要定义一个用于关系的辅助表。
对于这个辅助表, 强烈建议 不 使用模型,而是采用一个实际的表:

class Page(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    tags = db.relationship('Tag', secondary=tags,
        backref=db.backref('pages', lazy='dynamic'))

class Tag(db.Model):
    id = db.Column(db.Integer, primary_key=True)

tags = db.Table('tags',
    db.Column('tag_id', db.Integer, db.ForeignKey('tag.id')),
    db.Column('page_id', db.Integer, db.ForeignKey('page.id'))
)

这里我们配置 Page.tags 加载后作为标签的列表,因为我们并不期望每页出现太多的标签。而每个 tag 的页面列表( Tag.pages)是一个动态的反向引用。 正如上面提到的,这意味着您会得到一个可以发起 select 的查询对象。

4、绑定多个数据库

从 0.12 开始,Flask-SQLAlchemy 可以容易地连接到多个数据库。为了实现这个功能,预配置了 SQLAlchemy 来支持多个 “binds”。

示例配置

下面的配置声明了三个数据库连接。特殊的默认值和另外两个分别名为 users(用于用户)和appmeta 连接到一个提供只读访问应用内部数据的 sqlite 数据库):

SQLALCHEMY_DATABASE_URI = 'postgres://localhost/main'
SQLALCHEMY_BINDS = {
    'users':        'mysqldb://localhost/users',
    'appmeta':      'sqlite:////path/to/appmeta.db'
}
创建和删除表

create_all() 和 drop_all() 方法默认作用于所有声明的绑定(bind),包括默认的。
这个行为可以通过提供 bind 参数来定制。
它可以是单个绑定(bind)名, ‘all’ 指向所有绑定(binds)或一个绑定(bind)名的列表。
默认的绑定(bind)(SQLALCHEMY_DATABASE_URI) 名为 None:

>>> db.create_all()
>>> db.create_all(bind=['users'])
>>> db.create_all(bind='appmeta')
>>> db.drop_all(bind=None)
引用绑定

当您声明模型时,您可以用 bind_key 属性指定绑定(bind):

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

bind key 存储在表中的 info 字典中作为 ‘bind_key’ 键值。
了解这个很重要,因为当您想要直接创建一个表对象时,您会需要把它放在那:

user_favorites = db.Table('user_favorites',
    db.Column('user_id', db.Integer, db.ForeignKey('user.id')),
    db.Column('message_id', db.Integer, db.ForeignKey('message.id')),
    info={'bind_key': 'users'}
)

如果您在模型上指定了 bind_key ,您可以用它们准确地做您想要的。
模型会自行连 接到指定的数据库连接。

二、API

官网详解
这部分文档记录了 Flask-SQLAlchemy 里的所有公开的类和函数。

1、配置
2、模型
class flask.ext.sqlalchemy.Model
__bind_key__:
__tablename__:
query:
query_class:

class flask.ext.sqlalchemy.BaseQuery(entities, session=None)
all()
order_by()
limit()
offset()
first()
first_or_404()
get()
get_or_404()
paginate()
3、会话
class flask.ext.sqlalchemy.SignallingSession(db, autocommit=False, autoflush=True, app=None, **options)

4、实用工具
分页

class flask.ext.sqlalchemy.Pagination(query, page, per_page, total, items)¶
由BaseQuery.paginate()返回的内部帮助器类。

object = models.query.all().paginate()
'''
has_next
has_prev
items
iter_pages
next
next_num
page
pages
per_page
prev
prev_num
query
total
'''
查看SQL

flask.ext.sqlalchemy.get_debug_queries()
在调试模式下,Flask-SQLAlchemy将记录发送到数据库的所有SQL查询。

# 在配置文件中进行如下配置
SQLALCHEMY_RECORD_QUERIES=True
5、关联查询:
自关联:join

user.query.join()

发布了128 篇原创文章 · 获赞 0 · 访问量 2488

猜你喜欢

转载自blog.csdn.net/qq_41134008/article/details/105672736
今日推荐