- Flask默认并没有提供任何数据库操作的API,我们可以选择任何适合自己项目的数据库来使用。
- Flask中可以自己的选择数据,用原生语句实现功能,也可以选择ORM(SQLALCHEMY、MongoEngine)。
- 原生SQL缺点
- 代码利用率低,条件复杂代码语句越长,有很多相似语句,一些SQL是在业务逻辑中拼出来的,修改需要了解业务逻辑,直接写SQL容易忽视SQL问题。
- ORM
- 将对对象的操作转换为原生SQL
- 优点
- 易用性,可以有效减少重复SQL
- 性能损耗少
- 设计灵活,可以轻松实现复杂查询
- 移植性好
- Python的ORM(SQLALCHEMY)
- 针对于Flask的支持
SQLALCHEMY
- 安装
- pip install flask-sqlalchemy
- 数据库连接
- dialect+driver://username:password@host:port/database
- 数据库实现+数据库驱动://用户名:密码@主机名:端口/数据库名
- 连接数据库需要指定配置
- SQLALCHEMY_DATABASE_URI
- SQLALCHEMY_TRAKE_MODIFICATIONS = False 禁止对象追踪修改
SQLite数据库连接不需要额外驱动,也不需要用户名密码
- sqlite:///sqlite1.db
db = SQLAlchemy() db.init_app(app)
数据库使用
- 创建模型
class Persion(db.Model): __tablename__ = 'persion' id = db.Column(db.Integer,primary_key=True) name = db.Column(db.String(40),unique=True)
- 创建数据库
- db.create_all()
- 删除数据库
- db.drop_all()
- 数据操作
- 在事务中处理
- 数据插入
- db.session.add(object)
- db.session.add_all(list[objet])
- db.session.delete(object)
- db.session.commit()
- 修改和删除基于查询
常用约束
约束 | 说明 |
primary_key | 主键 |
autoincremment | 自增 |
unique | 非空 |
index | 索引 |
nullable | 是否可空 |
default | 默认值 |
Foreign Key() | 外键 |
数据查询
- 查询数据结果集
- 语法:类名.query.**
- 获取查询集
- all() 以列表的形式返回此查询所表示的结果。这将导致底层查询的执行。
- filter(类名.属性名.运算符(‘**’))
- filter( 类名.属性名.运算符 值)
- 运算符
运算符 | 说明 |
contains | |
startswith | |
endswith | |
in_ | |
like | |
__gt__ | |
__ge__ | |
__lt__ | |
__le__ |
- 筛选 API
筛选 | 说明 |
filter_by | 通过条件过滤 |
offset | 对查询应用偏移量并返回新生成的查询。 |
limit | 对查询应用一个限制并返回新生成的查询。 |
order_by | 将一个或多个ORDER BY 标准应用于查询并返回新生成的查询。 |
get | 返回基于给定主键标识符的实例,如果没有找到则返回None。 |
first | 返回此查询的第一个结果,如果结果不包含任何行,则返回None。这将导致底层查询的执行。 |
paginate | 从页页返回per_page项。默认情况下,如果没有找到任何项并且页面大于1,它将使用404中止。通过将error_out设置为False,可以禁用这种行为。 |
- 逻辑运算
- 与
- and_
- filter(and_(条件),条件…)
- 或
- or_
- filter(or_(条件),条件…)
- 非
- not_
- filter(not_(条件),条件…)
数据库分页显示
class flask_sqlalchemy.BaseQuery
(entities, session=None)
- SQLAlchemy查询子类,具有用于在web应用程序中查询的方便方法。
- 这是用于模型的默认查询对象,并公开为query。通过子类化并设置query_class,覆盖单个模型的query类 。
-
first_or_404
()- 与first()类似,但是如果没有找到,将中止并弹出 404 ,而不是返回None。
-
get_or_404
(ident)¶- 与get()类似,但是如果没有找到,就会终止 并弹出 404 ,而不是返回None。
-
paginate
(page=None, per_page=None, error_out=True, max_per_page=None)¶- 从 page page返回per_page 项。
- 如果page或per_page为None,它们将从request query中检索。如果max_per_page是指定的,per_page会被限制在那个值。 如果没有请求,或者它们不在查询中,它们将默认分别为1和20.
- 当error_out为True(默认)。以下规则将导致404响应:
- 没有找到任何项,并且page不是1。
- page小于1,或者per_page是负数。
- page或per_page不是整形。
- 当error_out是False,page和per_page分别默认为1和20.
- 返回
Pagination
对象。
class flask_sqlalchemy.Pagination
(query, page, per_page, total, items)
BaseQuery.paginate()
返回的内部助手类 。 如果使用其他库,还可以从任何其他SQLAlchemy查询对象构造它。- 此外,可以将None作为查询对象传递,在这种情况下,prev()和next()将不再工作。
- has_next
- 如果存在下一页,则为真
- has_prev
- 如果前一页存在,则为真
- items = None
- 当前页的items
-
iter_pages
(left_edge=2, left_current=2, right_current=5, right_edge=2) - 遍历分页中的页码。这四个参数控制阈值,应该从侧面产生多少个数字。跳过的页码表示为None。这是你如何在模板中呈现这样的分页:
{% macro render_pagination(pagination, endpoint) %} <div class=pagination> {%- for page in pagination.iter_pages() %} {% if page %} {% if page != pagination.page %} <a href="{{ url_for(endpoint, page=page) }}">{{ page }}</a> {% else %} <strong>{{ page }}</strong> {% endif %} {% else %} <span class=ellipsis>…</span> {% endif %} {%- endfor %} </div> {% endmacro %}
next
(error_out=False)- 返回下一页的
Pagination
对象。
- 返回下一页的
- next_num
- 下一页的编号
-
page
= None- 当前页码(1索引)
- pages
- 总页数
-
per_page
= None- 要显示在页面上的项数。
-
prev
(error_out=False)- 返回前一页的
Pagination
对象。
- 返回前一页的
- prev_num
- 前页的编号。
-
query
= None- 用于创建此分页对象的无限制查询对象。
-
total
= None- 匹配查询的项的总数