数据库操作

现在我们创建了模型,生成了数据库和表,下面来学习常用的数据库操作,数据库操作主要是CRUD,即Create(创建)、Read(读取/查询)、Update(更新)和Delete(删除)。

SQLAlchemy使用数据库会话来管理数据库操作,这里的数据库会话也称为事务(transaction)。 Flask-SQLAlchemy自动帮我们创建会话,可以通过db.session属性获取。

数据库中的会话代表一个临时存储区,你对数据库做出的改动都会存放在这里。你可以调用add()方法将新创建的对象添加到数据库会话中,或是对会话中的对象进行更新。只有当你对数据库会话对象调用commit()方法时,改动才会提交到数据库,这确保了数据提交的一致性。另外,数据库会话也支持回滚操作。当你对会话调用rollback()方法时,添加到会话中且未提交的改动都将被撤销。

CRUD

下面我们在python shell中操作CRUD操作。默认情况下,Flask-SQLALchemy(>=2.3.0版本)会自动为模型类生成一个__repr__()方法。当在python shell中调用模型类的对象时,__repr__()方法会返回一条类似”<模型类名主键值>”的字符串,比如<Note 2>。下面示例中,模型类都重新定义了__repr__()方法,返回一些更有用的信息,比如:

class Note(db.Model):
id = db.Column(db.Integer, primary_key=True)
db.Column()
body = db.Column(db.Text)
def __repr__(self):
# %r是用repr()方法处理对象,返回类型本身,而不进行类型转化
return '<Note %r>' % self.body

在实际开发中,这并不是必须的。

Create

添加一条新纪录到数据库分三步:

1)  创建python对象(实例化模型类)作为一条记录

2)  添加新创建的记录到数据库会话。

3)  提交数据库会话

下面的示例向数据库中添加了三条留言:

>>> from app import db, Note
>>> note1=Note(body='remember Sam Xia')
>>> note2 = Note(body='Rose')
>>> note3 = Note(body = 'I AM HERE TO TRUW BUBLEGUM AND KIK ASS, AND NOW I AM ALL OUT OF BUBLEGUM~')
>>> db.session.add(note1)
>>> db.session.add(note2)
>>> db.session.add(note3)
>>> db.session.commit()

在这个例子中,首先从app模块导入db对象和Note类,然后分别创建三个Note实例表示三条记录,使用关键字参数传入字段数据。我们的Note类继承自db.Model基类,db.Model基类会为Note类提供一个构造函数,接收匹配类属性名称的参数值,并赋值给对应的类属性,所以我们不需要自己在Note类中定义构造方法。接着我们调用add()方法把这三个Note对象添加到会话对象db.session中,最后调用commit()方法提交会话。

除了依次调用add()方法添加多个记录,也可以使用add_all()依次添加包含所有记录对象的列表。

我们在创建模型类实例的时候并没有定义id字段的数据,这是因为主键由SQLAlchemy管理。模型类对象创建后作为临时对象(transient),当你提交数据库会话后,模型类对象才会转换为数据库记录写入数据库中,这时模型类对象会自动获取id值:

>>> note2.id

3

Flask-SQLAlchemy提供了一个SQLALCHEMY_COMMIT_ON_TEARDOWN配置,将其设为True可以设置自动调用commit()方法提交数据库会话。因为存在潜在的Bug,目前不建议使用。

可以使用db.session.commit()方法的方式提交数据库会话。

Read

如何从数据库取回数据呢,使用模型类提供的query属性附加调用各种过滤方法及查询方法可以完成这个任务。

一般来说,一个完整的查询遵循下面的模式:

<模型类>.query.<过滤方法>.<查询方法>

从某个模型类触发,通过在query属性对应的Query对象上附加的过滤方法和查询函数对模型类对应的表中的记录进行各种筛选和调整,最终返回包含对应数据库记录数据的模型类实例,对返回的实例调用属性即可获取对应的字段数据。

SQLAlchemy提供了许多查询方法用来获取记录,如下表:

表中的first_or_404()、get_or_404()以及paginate()方法是Flask-SQLAlchemy附加的查询方法。

下面是对Note类进行查询的几个例子。all()返回所有记录:

>>> Note.query.all()
[<Note u'Hello~'>, <Note u'remember Sam Xia'>, <Note u'Rose'>, <Note u'I AM HERE TO TRUW BUBLEGUM AND KIK ASS, AND NOW I AM ALL OUT OF BUBLEGUM~'>]
first()返回第一条记录:
>>> note1 = Note.query.first()
>>> note1
<Note u'Hello~'>
get()返回指定主键值(id字段)的记录:
>>> note2=Note.query.get(2)
>>> note2
<Note u'remember Sam Xia'>
>>> note2.body
u'remember Sam Xia'
count()返回记录的数量:
>>> Note.query.count()
4

SQLAlchemy还提供了许多过滤方法,使用这些过滤方法可以获取更精确的查询,比如获取指定字段值的记录。对模型类的query属性存储的query对象调用过滤方法将返回一个更精确的query对象(简称为查询对象)。因为每个过滤方法都会返回新的查询对象,所以过滤器可以叠加使用。在查询对象上调用前面说的查询方法,即可获得一个包含过滤后的记录的列表。常用的查询过滤方法如下所示:

filter()方法

filter()方法是最基础的查询方法。它使用指定的规则来过滤记录,下面的示例在数据库里找出了body字段值为”Rose”的记录:

>>> Note.query.filter(Note.body=='Rose').first()
<Note u'Rose'>

直接打印查询对象或将其转换为字符串可以查看对应当前SQL语句:

>>> print  Note.query.filter_by(body='Rose')
SELECT note.id AS note_id, note.body AS note_body
FROM note
WHERE note.body = ?

在filter()方法中传入表达式时,除了”==”以及表示不等于的”!=”,其他常用的查询操作符以及使用示例如下所示:

like:
>>> Note.query.filter(Note.body.like('%Sam%')).first()
<Note u'remember Sam Xia'>
in:
>>> Note.query.filter(Note.body.in_(['Rose','Sam'])).first()
<Note u'Rose'>
not in:
>>> Note.query.filter(~Note.body.in_(['foo'])).all()
[<Note u'Hello~'>, <Note u'remember Sam Xia'>, <Note u'Rose'>, <Note u'I AM HERE TO TRUW BUBLEGUM AND KIK ASS, AND NOW I AM ALL OUT OF BUBLEGUM~'>]
and:

使用and_()

>>>from sqlalchemy import and_
>>> Note.query.filter(and_(Note.body == 'Rose', Note.id == 3)).all()
[<Note u'Rose'>]

或者再filter()中加入多个表达式,使用逗号分隔

>>> Note.query.filter(Note.body == 'Rose', Note.id == 3).all()
[<Note u'Rose'>]

或叠加调用多个filter()/filter_by()方法

filter()中的等号是两个

>>> Note.query.filter(Note.body == 'Rose').filter(Note.id == 3).all()
[<Note u'Rose'>]

注意filter_by()中的等号是一个

>>> Note.query.filter_by(body='Rose').filter_by(id=3).all()
[<Note u'Rose'>]
or:
>>> Note.query.filter(or_(Note.body == 'Rose', Note.id == 2)).all()
[<Note u'remember Sam Xia'>, <Note u'Rose'>]

和filter()方法相比,filter_by()方法更易于使用。在filter_by()方法中,可以使用关键字表达式来指定过滤规则。更方便的是,可以在这个过滤器中直接使用字段名称。下面的例使用filter_by()过滤器完成了同样的任务:

>>> Note.query.filter_by(body = 'Rose').all()
[<Note u'Rose'>]
update

更新一条记录分拣单,直接赋值给模型类的字段属性就可以改变字段值,然后调用gcommit()方法提交会话即可,例如:

>>> note = Note.query.get(2)
>>> note.body
u'remember Sam Xia'
>>> note.body = 'Life is a dream'
>>> db.session.commit()
>>> note.body
u'Life is a dream'

只有要插入新的记录或要将现有的记录添加到会话中时才需要使用add()方法,单纯要更新现有的记录时只需要直接为属性赋新值,然后提交会话。

delete

删除记录和添加记录相似,不过要把add()方法换成delete()方法,最后都要调用commit()方法提交记录。

例如删除id(主键)为2的记录:

>>> note = Note.query.get(1)
>>> db.session.delete(note)
>>> db.session.commit()

flask 数据库操作(增删改查)的更多相关文章

  1. Yii数据库操作增删改查-[增加\查询\更新\删除 AR模式]

    在Yii的开发中常常需要去使用Yii的增删改查方法,这些方法又可以多次变化和组合,带来全方位的实现对数据库的处理,下面对这些方法做一些简单的整理和梳理,有遗漏或是BUG,敬请指出.灰常感谢!!! 一. ...

  2. Django数据库操作(增删改查)

    Django数据库操作(增删改查) 创建数据库中的一个表 class Business(models.Model): #自动创建ID列 caption = models.CharField(max_l ...

  3. Android下数据库操作——增删改查

    Android下数据库第一种方式增删改查     1.创建一个帮助类的对象,调用getReadableDatabase方法,返回一个SqliteDatebase对象     2.使用SqliteDat ...

  4. spring框架学习之--数据库操作增删改查

    基于spring的NamedParameterJdbcTemplate操作数据库 首先在 resources 文件夹下添加数据库配置文件jdbc.properties 配置常用的数据库信息 consu ...

  5. SpringBoot 数据库操作 增删改查

    1.pom添加依赖 <!--数据库相关配置--> <dependency> <groupId>org.springframework.boot</groupI ...

  6. Yii2.0数据库操作增删改查详解

    1.简单查询: one(): 根据查询结果返回查询的第一条记录. all(): 根据查询结果返回所有记录. count(): 返回记录的数量. sum(): 返回指定列的总数. average():  ...

  7. django数据库操作-增删改查-多对多关系以及一对多(外键)关系

    一.一对多(外键) 例子:一个作者对应多本书,一本书只有一个作者 model代码: class Person(models.Model); name = models.CharField('作者姓名' ...

  8. 转: django数据库操作-增删改查-多对多关系以及一对多(外键)关系

    原文链接:http://blog.csdn.net/u010271717/article/details/22044415 一.一对多(外键) 例子:一个作者对应多本书,一本书只有一个作者 model ...

  9. 使用JDBC连接MySQL数据库操作增删改查

    目录 1.首先这个Myeclipse的包名以及一些实现的类(这样子写是我的习惯) 2.接下来我们创建数据库(MySQL) 3.在数据库里面添加数据 4.首先是BaseDao,这个是重中之重,注意那个数 ...

  10. 通过Loadruner对mysql数据库进行增删改查

    操作mysql数据库,是在实现mysql数据源配置的基础上操作,可先阅读:loadrunner参数化使用mysql数据源失败解决方法 写之前先理一下,数据库访问流程:打开数据库  --> 数据库 ...

随机推荐

  1. Spring 注解 @Scheduled(cron = "0 0/10 * * * ? ") 动态改变时间

    import java.util.Date; import java.util.concurrent.Executor; import java.util.concurrent.Executors; ...

  2. OC动画:CAAnimationGroup

    //贝塞尔曲线路径 UIBezierPath *movePath = [UIBezierPath bezierPath]; [movePath moveToPoint:CGPointMake(10.0 ...

  3. 小程序-formdata传参

    项目背景,后端接口要求formData传参: 在util.js文件中封装转化函数,代码如下: const formatTime = date => { const year = date.get ...

  4. js计算常见操作

    如何实现数字相加 var a = 1, var b = 2, var c = a + b 这样c得出来的解果是12, 使用Number()函数可以解决这个问题,如下 var c = Number(a) ...

  5. 接口,定义接口的关键字是 interface 实现接口关键字是 implements

    当抽象类中的方法都是抽象的时候,这时可以将该抽象类用另一种形式定义和表示,就是接口interface特点:对于接口中常见的成员:而且这些成员都有固定的修饰符,不写就默认存在1:全局常量 :  都是 p ...

  6. Lua 随机数生成问题

    原文链接:http://blog.csdn.net/zhangxaochen/article/details/8095007 Lua 生成随机数需要用到两个函数: math.randomseed(xx ...

  7. 解决Linux 下 root用户删除文件提示:Operation not permitted

    问题描述 用最高权限rm文件,居然报错Operation not permitted.查看权限也没有问题.可想而知有可能文件被保护了.用命令lsattr检查一下就知道. [root@linux roo ...

  8. (转)以太坊(Ethereum ETH)的奖励机制

    如果问一块显卡它最恨什么,那么答案一定是以太坊.以太坊,矿工为之疯狂,显卡为之颤抖,游戏玩家为之骂娘. 然而,除了购买矿机.连接矿池.卖币套现之外,是否有人关注过以太坊的奖励机制呢? 且听我慢慢道来. ...

  9. dblink连接操作远程数据库

    在一个数据库中需要操作远程数据库时,需要创建远程数据库的连接. 连接代码如下: create public database link 连接名 connect to 远程数据库用户名 identifi ...

  10. js神秘的电报密码---哈弗曼编码

    哈夫曼编码,根据每个单词在文本中出现的次数频率为权值,频率高的权值大.然后每次取两个频率最小的生成树,最后生成一颗大树.从根节点到该单词的路径,左边为0,右边为1, function HFM(){ v ...