flask-sqlalchemy怎么使用?

2020-06-08 08:23发布

2条回答
大泽九章
2楼 · 2020-06-08 08:48

image.png

代码如上


无需指教
3楼 · 2020-06-08 09:09

一. 安装

$ pip install flask-sqlalchemy

二. 配置

配置选项列表 :

选项说明
SQLALCHEMY_DATABASE_URI用于连接的数据库 URI 。例如:sqlite:////tmp/test.db 或 mysql://username:password@server/db
SQLALCHEMY_BINDS一个映射 binds 到连接 URI 的字典。更多 binds 的信息见 用 Binds 操作多个数据库 。
SQLALCHEMY_ECHO如果设置为 Ture , SQLAlchemy 会记录所有 发给 stderr 的语句,这对调试有用。
SQLALCHEMY_RECORD_QUERIES可以用于显式地禁用或启用查询记录。查询记录 在调试或测试模式自动启用。更多信息见 get_debug_queries() 。

SQLALCHEMY_NATIVE_UNICODE | 可以用于显式禁用原生 unicode 支持。当使用 不合适的指定无编码的数据库默认值时,这对于 一些数据库适配器是必须的(比如 Ubuntu 上某些版本的 PostgreSQL )。|
| SQLALCHEMY_POOL_SIZE | 数据库连接池的大小。默认是引擎默认值(通常 是 5 ) |
| SQLALCHEMY_POOL_TIMEOUT | 设定连接池的连接超时时间。默认是 10 。 |
| SQLALCHEMY_POOL_RECYCLE | 多少秒后自动回收连接。这对 MySQL 是必要的, 它默认移除闲置多于 8 小时的连接。注意如果 使用了 MySQL , Flask-SQLALchemy 自动设定这个值为 2 小时。|

app.config["SQLALCHEMY_DATABASE_URI"] = DATABASE_URIapp.config["SQLALCHEMY_COMMIT_ON_TEARDOWN"] = True/False  # 每次请求结束后都会自动提交数据库中的变动.app.config[""] =app.config[""] =app.config[""] =app.config[""] =DATABASE_URI :mysql : mysql://username:password@hostname/databasepgsql : postgresql://username:password@hostname/databasesqlite(linux)  : sqlite:////absolute/path/to/databasesqlite(windows) : sqlite:///c:/absolute/path/to/database

三. 初始化示例

from flask import Flaskfrom flask_sqlalchemy import SQLAlchemybase_dir = os.path.abspath(os.path.dirname(__file__))app = Flask(__name__)app.config["SQLALCHEMY_DATABASE_URI"] = 'sqlite:///' + os.path.join(base_dir, 'data.sqlite')app.config["SQLALCHEMY_COMMIT_ON_TEARDOWN"] = Truedb = SQLAlchemy(app)

四. 定义模型

模型 表示程序使用的持久化实体. 在 ORM 中, 模型一般是一个 Python 类, 类中的属性对应数据库中的表.

Flaks-SQLAlchemy 创建的数据库实例为模型提供了一个基类以及一些列辅助类和辅助函数, 可用于定义模型的结构.

db.Model    # 创建模型,db.Column   # 创建模型属性.

模型属性类型 :

类型名Python类型说明
Integerint普通整数,一般是 32 位
SmallIntegerint取值范围小的整数,一般是 16 位
Big Integerint 或 long不限制精度的整数
Floatfloat浮点数
Numericdecimal.Decimal定点数
Stringstr变长字符串
Textstr变长字符串,对较长或不限长度的字符串做了优化
Unicodeunicode变长 Unicode 字符串
Unicode Textunicode变长 Unicode 字符串,对较长或不限长度的字符串做了优化
Booleanbool布尔值
Datedatetime.date日期
Timedatetime.time时间
DateTimedatetime.datetime日期和时间
Intervaldatetime.timedelta时间间隔
Enumstr一组字符串
PickleType任何 Python 对象自动使用 Pickle 序列化
LargeBinarystr二进制文件

常用 SQLAlchemy 列选项

选项名说明
primary_key如果设为 True,这列就是表的主键
unique如果设为 True,这列不允许出现重复的值
index如果设为 True,为这列创建索引,提升查询效率
nullable如果设为 True,这列允许使用空值;如果设为 False,这列不允许使用空值
default为这列定义默认值

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

示例 :

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 '' % self.nameclass 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 '' % self.username

五. 关系

关系型数据库使用关系把不同表中的行联系起来.

常用 SQLAlchemy 关系选项 :

选项名说明
backref在关系的另一个模型中添加反向引用
primaryjoin明确指定两个模型之间使用的联结条件。只在模棱两可的关系中需要指定.
lazy指定如何加载相关记录。可选值如下 :

select(首次访问时按需加载)

immediate(源对象加载后就加载)

joined(加载记录,但使用联结)

subquery(立即加载,但使用子查询)

noload(永不加载)

dynamic(不加载记录,但提供加载记录的查询)
uselist如果设为 Fales,不使用列表,而使用标量值
order_by指定关系中记录的排序方式
secondary指定多对多关系中关系表的名字
secondaryjoinSQLAlchemy 无法自行决定时,指定多对多关系中的二级联结条件

1) 一对多

原理 : 在 “多” 这一侧加入一个外键, 指定 “一” 这一侧联结的记录.

示例代码 : 一个角色可属于多个用户, 而每个用户只能有一个角色.

class Role(db.Model):# ...users = db.relationship('User', backref='role')class User(db.Model):# ...role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))  # 外键关系.###############db.ForeignKey('roles.id') : 外键关系,Role.users = db.relationship('User', backref='role') : 代表 外键关系的 面向对象视角. 对于一个 Role 类的实例, 其 users 属性将返回与角色相关联的用户组成的列表.db.relationship() 第一个参数表示这个关系的另一端是哪个模型.backref 参数, 向 User 模型添加了一个 role 数据属性, 从而定义反向关系.  这一属性可替代 role_id 访问 Role 模型, 此时获取的是模型对象, 而不是外键的值.

2) 多对多

最复杂的关系类型, 需要用到第三章表, 即 关联表 , 这样多对多关系可以分解成原表和关联表之间的两个一对多关系.

查询多对多关系分两步 : 遍历两个关系来获取查询结果.

代码示例:

registrations = db.Table("registrations",db.Column("student_id", db.Integer, db.ForeignKey("students.id")),db.Column("class_id", db.Integer, db.ForeignKey("classes.id")))class Student(db.Model):__tablename__ = "students"id = db.Column(db.Integer, primary_key=True)name = db.Column(db.String)classes = db.relationship("Class",secondary=registrations,backref=db.backref("students", lazy="dynamic"),lazy="dynamic")class Class(db.Model):__tablename__ = "classes"id = db.Column(db.Integer, primary_key=True)name = db.Column(db.String)

多对多关系仍然使用定义一对多关系的 db.relationship() 方法进行定义, 但在多对多关系中, 必须把 secondary 参数设为 关联表.

多对多关系可以在任何一个类中定义, backref 参数会处理好关系的另一侧.

关联表就是一个简单的表, 不是模型, SQLAlchemy 会自动接管这个表.

classes 关系使用列表语义, 这样处理多对多关系比较简单.

Class 模型的 students 关系有 参数 db.backref() 定义. 这个关系还指定了 lazy 参数, 所以, 关系两侧返回的查询都可接受额外的过滤器.

自引用关系
自引用关系可以理解为 多对多关系的特殊形式 : 多对多关系的两边由两个实体变为 一个实体.

高级多对多关系
使用多对多关系时, 往往需要存储所联两个实体之间的额外信息. 这种信息只能存储在关联表中. 对用户之间的关注来说, 可以存储用户关注另一个用户的日期, 这样就能按照时间顺序列出所有关注者.

为了能在关系中处理自定义的数据, 必须提升关联表的地位, 使其变成程序可访问的模型.

关注关联表模型实现:

class Follow(db.Model):__tablename__ = "follows"follower_id = db.Column(db.Integer, db.ForeignKey("users.id"), primary_key=True)followed_id = db.Column(db.Integer, db.ForeignKey("users.id"), primary_key=True)timestamp = db.Column(db.DateTime, default=datetime.utcnow)# SQLAlchemy 不能直接使用这个关联表, 因为如果这个做程序就无法访问其中的自定义字段. 相反的, 要把这个多对多关系的左右两侧拆分成两个基本的一对多关系, 而且要定义成标准的关系.

使用两个一对多关系实现的多对多关系:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class User(UserMixin, db.Model):
    # ...
    followd = db.relationship("Follow",
                              foreign_keys=[Follow.follower_id],
                              backref=db.backref("follower", lazy="joined"),
                              lazy="dynamic",
                              cascade="all, delete-orphan")
    followrs = db.relationship("Follow",
                              foreign_keys=[Follow.followed_id],
                              backref=db.backref("followed", lazy="joined"),
                              lazy="dynamic",
                              cascade="all, delete-orphan")

# 这段代码中, followed 和 follower 关系都定义为 单独的 一对多关系. 
# 注意: 为了消除外键歧义, 定义关系是必须使用可选参数 foreign_keys 指定的外键. 而且 db.backref() 参数并不是指定这两个关系之间的引用关系, 而是回引 Follow 模型. 回引中的 lazy="joined" , 该模式可以实现立即从连接查询中加载相关对象.
# 这两个关系中, user 一侧设定的 lazy 参数作用不一样. lazy 参数都在 "一" 这一侧设定, 返回的结果是 "多" 这一侧中的记录. dynamic 参数, 返回的是查询对象.
# cascade 参数配置在父对象上执行的操作相关对象的影响. 比如, 层叠对象可设定为: 将用户添加到数据库会话后, 要自定把所有关系的对象都添加到会话中. 删除对象时, 默认的层叠行为是把对象联结的所有相关对象的外键设为空值. 但在关联表中, 删除记录后正确的行为是把执行该记录的实体也删除, 因为这样才能有效销毁联结. 这就是 层叠选项值 delete-orphan 的作用. 设为 all, delete-orphan 的意思是启动所有默认层叠选项, 并且还要删除孤儿记录.

3) 一对一

可以看做特殊的 一对多 关系. 但调用 db.relationship() 时 要把 uselist 设置 False, 把 多变为 一 .

4) 多对一

将 一对多 关系,反过来即可, 也是 一对多关系.

六. 数据库操作

1) 创建数据库及数据表

创建数据库

db.create_all()

示例 :
$ python myflask.py shell
> from myflask import db
> db.create_all()

如果使用 sqlite , 会在 SQLALCHEMY_DATABASE_URI 指定的目录下 多一个文件, 文件名为该配置中的文件名.

如果数据库表已经存在于数据库中, 那么 db.create_all() 不会创建或更新这个表.

更新数据库
方法一 :
先删除, 在创建 –> 原有数据库中的数据, 都会消失.

> db.drop_all()> db.create_all()



相关问题推荐

  • 回答 3

    换行。比如,print hello\nworld效果就是helloworld\n就是一个换行符。\是转义的意思,'\n'是换行,'\t'是tab,'\\'是,\ 是在编写程序中句子太长百,人为换行后加上\但print出来是一整行。...

  • 回答 42

    十种常见排序算法一般分为以下几种:(1)非线性时间比较类排序:a. 交换类排序(快速排序、冒泡排序)b. 插入类排序(简单插入排序、希尔排序)c. 选择类排序(简单选择排序、堆排序)d. 归并排序(二路归并排序、多路归并排序)(2)线性时间非比较类排序:...

  • 回答 70
    已采纳

    前景很好,中国正在产业升级,工业机器人和人工智能方面都会是强烈的热点,而且正好是在3~5年以后的时间。难度,肯定高,要求你有创新的思维能力,高数中的微积分、数列等等必须得非常好,软件编程(基础的应用最广泛的语言:C/C++)必须得很好,微电子(数字电...

  • 回答 28

    迭代器与生成器的区别:(1)生成器:生成器本质上就是一个函数,它记住了上一次返回时在函数体中的位置。对生成器函数的第二次(或第n次)调用,跳转到函数上一次挂起的位置。而且记录了程序执行的上下文。生成器不仅记住了它的数据状态,生成器还记住了程序...

  • 回答 9

    python中title( )属于python中字符串函数,返回’标题化‘的字符串,就是单词的开头为大写,其余为小写

  • 回答 6

    第一种解释:代码中的cnt是count的简称,一种电脑计算机内部的数学函数的名字,在Excel办公软件中计算参数列表中的数字项的个数;在数据库( sq| server或者access )中可以用来统计符合条件的数据条数。函数COUNT在计数时,将把数值型的数字计算进去;但是...

  • 回答 1

    head是方法,所以需要取小括号,即dataset.head()显示的则是前5行。data[:, :-1]和data[:, -1]。另外,如果想通过位置取数据,请使用iloc,即dataset.iloc[:, :-1]和dataset.iloc[:, -1],前者表示的是取所有行,但不包括最后一列的数据,结果是个DataFrame。...

  • Python入门简单吗2021-09-23 13:21
    回答 45

    挺简单的,其实课程内容没有我们想象的那么难、像我之前同学,完全零基础,培训了半年,直接出来就工作了,人家还在北京大公司上班,一个月15k,实力老厉害了

  • 回答 4

    Python针对众多的类型,提供了众多的内建函数来处理(内建是相对于导入import来说的,后面学习到包package时,将会介绍),这些内建函数功用在于其往往可对多种类型对象进行类似的操作,即多种类型对象的共有的操作;如果某种操作只对特殊的某一类对象可行,Pyt...

  • 回答 8

     相当于 ... 这里不是注释

  • 回答 4

    还有FIXME

  • 回答 3

    python的两个库:xlrd和xlutils。 xlrd打开excel,但是打开的excel并不能直接写入数据,需要用xlutils主要是复制一份出来,实现后续的写入功能。

  • 回答 8

    单行注释:Python中的单行注释一般是以#开头的,#右边的文字都会被当做解释说明的内容,不会被当做执行的程序。为了保证代码的可读性,一般会在#后面加一两个空格然后在编写解释内容。示例:#  单行注释print(hello world)注释可以放在代码上面也可以放在代...

  • 回答 2

    主要是按行读取,然后就是写出判断逻辑来勘测行是否为注视行,空行,编码行其他的:import linecachefile=open('3_2.txt','r')linecount=len(file.readlines())linecache.getline('3_2.txt',linecount)这样做的过程中发现一个问题,...

  • 回答 4

    或许是里面有没被注释的代码

  • 回答 26

    自学的话要看个人情况,可以先在B站找一下视频看一下

没有解决我的问题,去提问