文章目录

  • 1 什么是ORM?
  • 2 为什么要有ORM?
  • 3 如何在Flask应用ORM?
    • 3.1 连接数据库:
    • 3.2 数据库模型
      • **3.2.1 什么是数据库模型?**
      • **3.2.2 数据库模型实例:**
      • **3.2.3 常用的字段类型表:**
      • **3.2.4** Column常用参数表:
        • **server_default常用配置**
      • **3.2.5 将写好的模型映射到数据库。**
      • 3.2.6 更新模型
    • 3.3 数据库操作
      • 3.3.1 增
        • **实例3.3.1.1: 新增实例**
      • 3.3.2 查
        • **实例3.3.2.1: 查询实例**
      • 3.3.3 改
        • **实例3.3.3.1: 修改实例**
      • 3.3.4 删
        • **实例3.3.4.1: 删除实例**

数据库,顾名思义是储存数据的仓库,常见的管理数据库的软件被称为数据库管理系统(DBMS, Database Management System), 常见的DBMS有 MySQL、PostgreSQL、SQLite、MongoDB。这些常见的DBMS我们可以把他们理解为专门负责搬运数据的管理的数据的程序。

1 什么是ORM?

对象关系映射(英语:(Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换 。 ORM是“对象-关系-映射”的简称。在我们的web应用开发中ORM把底层的SQL数据实体转化成高层的Python对象。只需要通过Python代码即可完成数据库操作。

2 为什么要有ORM?

在web应用里使用原生的SQL语句操作数据库固然能达到我们处理储存数据的需求,但是会存在以下三类问题:

  • 手动编写SQL语句比较复杂耗时(当然因人而异,如果热衷于原生sql,并不影响开发),并且视图函数中写大量SQL语句会降低代码的易读性。
  • 比较容易出现安全问题,如SQL注入。
  • 对于不同的DBMS,需要使用不同的Python接口库,语法各不相同,很难有标准化的代码流程。

使用ORM可以很大程度上解决这些问题,在python中,ORM把底层的SQL数据实体转化成高层的Python对象。这样的好处是,你甚至不需要了解SQL,只需要操作Python对象的即可完成数据库操作。

使用ORM的优势:

  • 提升开发效率。从高层对象转换成原生SQL会牺牲一些性能,但这微不足道的性能牺牲换取的是巨大开发效率提升。
  • 可移植性好。它实现了数据库模型与DEMS的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库。通常一个orm支持很多的DEMS,如MySQL、PostgreSQL、Oracle、SQLite等,这极大的减轻了开发人员的工作量,不需要面对因数据库变更而导致的无效劳动。

3 如何在Flask应用ORM?

选择ORM框架时,在我们Flask中更推荐使用Flask的扩展组件Flask-SQLchemy 。Python实现的ORM有SQLAlchemy、Peewee、PonyORM等,其中SQLAlchemy是Python社区使用最广泛的ORM之一,Flask-SQLchemy正是基于SQLAlchemy。

3.1 连接数据库:

首先切入到我们的虚拟环境 ,安装我们的 Flask-SQLAlchemy

pip install flask-sqlalchemy
pip install pymysql

这里我们的DBMSmysql数据库为例, 连接数据库

实例

from flask import Flask
from flask_sqlalchemy import SQLAlchemyapp = Flask(__name__)
HOST = '127.0.0.1'
PORT = '3306'
DATABASE_NAME = '01_db'
USERNAME = 'root'
PASSWORD = 'qwer'DB_URI = "mysql+pymysql://{username}:{password}@{host}:{port}/{databasename}?charset=utf8mb4"\
.format(username=USERNAME,password=PASSWORD,host=HOST,port=PORT,databasename=DATABASE_NAME)app.config['SQLALCHEMY_DATABASE_URI'] = DB_URI
app.config['SQLALCHEMY_TRACK_MODIFICATIONS']= Falsedb = SQLAlchemy(app)

解读:

1flask_sqlalchemy模块中导入SQLAlchemy

from flask_sqlalchemy import SQLAlchemy

2 app对象通过变量SQLALCHEMY_DATABASE_URI加载配置好的URI(统一资源标识符),URI内包含了各种用于连接数据库的信息,指向一个具体的库。

常用数据库的URI格式

HOST = '127.0.0.1'  # ip
PORT = '3306'        # 端口
USERNAME = 'root'    # 数据库账号
PASSWORD = 'root'   # 密码
DATABASE_NAME = '01_db'  # 具体的一个库名
DB_URI = "mysql+pymysql://{username}:{password}@{host}:{port}/{databasename}?charset=utf8mb4"\
.format(username=USERNAME,password=PASSWORD,host=HOST,port=PORT,databasename=DATABASE_NAME)app.config['SQLALCHEMY_DATABASE_URI'] = DB_URI

3 SQLALCHEMY_TRACK_MODIFICATIONS这个配置变量决定是否追踪对象的修改,这用于FLask-SQLALchemy的事件通知系统。这个配置键默认值为None,如果没有特殊需要我们把它设置为Flase, 避免造成一些没必要的性能浪费。

app.config['SQLALCHEMY_TRACK_MODIFICATIONS']= False

4 SQLAlchemy类传入app类,引用app配置定位到具体的数据库,并且实例化出db对象,这个db对象代表我们的数据库,并且通过这个对象操作我们的ORM

db = SQLAlchemy(app)

3.2 数据库模型

3.2.1 什么是数据库模型?

继承了db.Model的python类,并且这个python类映射到数据库为一个表,这个python类称之为数据库模型。每个数据库模型都对应着数据库中的一个表。

3.2.2 数据库模型实例:

class UserInfo(db.Model):__tablename__ = 'user_info'id = db.Column(db.Integer, primary_key=True, autoincrement=True)username = db.Column(db.String(20), nullable=False)
  • __tablename__可以直接指定表名(推荐使用)。如果没有写__tablename__指定表名,此类名可以自动转化为表名(不推荐使用)。

    • 类名自动转化表名的方式为User–> user# 单个单词转换为小写
      UserInfo–> user_info # 多个单词转换为小写并使用下划线分隔
    • 如UserInfo类在没有__tablename__指定表名时候,UserInfo类会自动映射到数据库的表名为user_info
  • db.Column类实例化表示字段(表示数据库中的列),该类实例化出的对象被一个变量接受,该变量表示字段名。该类实例化时传入的参数表示字段的约束。
    • 如:id = db.Column(db.Integer,primary_key=True,autoincrement=True)表示该表内id字段为主键并且自动增长。

3.2.3 常用的字段类型表:

字段 说明 映射到数据库对应类型
Integer 整数 int类型
String 字符串,String类内可选择length参数的值用于设置最大字符个数 varchar类型
Text 用于储存较长的Unicode文本,,理论上可以储存65535个字节 text类型
Date 日期,存储Pythondatetime.date 对象 date类型
Time 时间,存储Pythondatetime.time 对象 time类型
DateTime 时间和日期,存储Pythondatetime 对象 datetime类型
Float 浮点类型 float类型
Double 双精度浮点类型,比浮点类型小数位精度更高。 double类型,占据64位。
Boolean 布尔值 tinyint类型
Enum 枚举类型 enum类型

3.2.4 Column常用参数表:

约束 说明
primary_key 如果设为True,该列就是表的主键
unique 如果设为True,该列每个值唯一,也就是该字段不允许出现重复值
index 如果设为True,为这列创建索引,用于提升查询效率
nullable 如果设为True,这列允许使用空值,反之则不允许使用空值。
server_default 为这列定义默认值, 默认值只支持字符串,其他类型需要db.text()方法指定
default 为这列定义默认值,但是该约束并不会真正映射到表结构中,该约束只会在ORM层面实现(不推荐使用)
comment 该字段的注释
name 可以使用该参数直接指定字段名
autoincrement 设置这个字段为自动增长的。

server_default常用配置

配置默认值类型 代码
更新datatime时间 server_default = db.text(“CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP”)
当前的datatime时间 server_default = db.text(“CURRENT_TIMESTAMP”)
数字 server_default=“数字”
布尔 server_default=db.text(‘True’) / server_default=db.text(‘False’)/ server_default=‘数字’

3.2.5 将写好的模型映射到数据库。

class UserInfo(db.Model):__tablename__ = 'user_info'id = db.Column(db.Integer,primary_key=True,autoincrement=True)username = db.Column(db.String(20),nullable=False)db.create_all()

如果你已经定义好了一个继承db.Model的类,我们把这个类称之为模型。我们想把这个模型映射到数据库中,也就是在数据库中创建这个模型所描述的一张表,使用db.create_all()可以实现把继承了该db.model的所有模型创建到数据库中。查看数据库的时候我们会发现多了一张user_info表。

3.2.6 更新模型

如果我们要更新一个模型,并且想把这个新的模型映射到数据库中,直接使用db.create_all()会无效,因为原来已经存在了这张表,为了解决这个问题我们可以先db.drop_all()删除该库下的所有继承了db.model的模型表,然后再db.create_all()使得继承了db.model的所有模型表映射到数据库中,从而创建我们更新的表。这种方式的原理是先删除数据库中原来所有的模型表,然后在新建所有需要映射的模型表,这种方式的弊端是它把数据库中原有的数据都销毁了。

为了解决这种更新模型导致删除掉原来的数据的弊端。下一章将会介绍一种更好的方式用于更新数据库。

3.3 数据库操作

3.3.1 增

模型表 映射到数据中

class School(db.Model):__tablename__ = "school"id = db.Column(db.Integer,primary_key=True,nullable=False,autoincrement=True,comment="ID")name = db.Column(db.String(30),nullable=False,server_default='',comment="学校名称")area = db.Column(db.String(30),nullable=False,server_default='',comment="所属地区")score = db.Column(db.Integer,nullable=False,server_default='600',comment="录取分数线")def __repr__(self):return "<School(name:{})>".format(self.name)db.create_all()

实例3.3.1.1: 新增实例

新增四条记录映射到数据库中

school_01 =School(name="北京大学",area="北京",score=658)  # 实例化模型类作为一条记录
school_02 =School(name="清华大学",area="北京",score=667)
school_03 =School(name="中山大学",area="广东",score=645)
school_04 =School(name="复旦大学",area="上海",score=650)db.session.add(school_01)   # 把新创建的记录添加到数据库会话
db.session.add(school_02)
db.session.add(school_03)
db.session.add(school_04)db.session.commit()  # 提交数据库会话

提示:数据库会话db.session和后面介绍的Flasksession对象没有关系。db.session是数据库会话也称为事务。

  1. 实例化模型类创建对象,该对象作为一条记录,实例化的过程传入的参数为字段内容。
  2. 把新创建的记录添加到数据库会话。
  3. 提交数据库会话

查看数据库

提示1 :如果add多条记录可以使用add_all()一次添加包含多条记录的列表

如:db.session.add_all([school_01,school_02,school_03,school_04])

3.3.2 查

在我们的flask中db.session出的对象调用query属性,可以通过query属性调用各种过滤方法完成查询。

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

常用过滤器表:

过滤器 说明
filter() 使用指定的规则过滤记录相当于sql的where约束条件,返回一个新查询
filter_by() 同filter原理,不同的是查询的时要使用关键字参数,返回一个新查询
limit() 使用指定的值限制原查询返回的结果的数量,返回一个新查询
offset() 偏移原查询返回的结果,返回一个新查询
order_by() 根据指定条件对原查询结构进行排序,返回一个新查询
group_by() 根据指定条件对原来查询结构进行分组,返回一个新查询

实例3.3.2.1: 查询实例

下面几个查询案例需要在实例3.3.1完成的基础上操作

all()返回一个列表,列表里存放所有符合条件的记录

all_school = School.query.all()
print(all_school) # 输出:[<School(name:北京大学)>, <School(name:清华大学)>, <School(name:中山大学)>, <School(name:复旦大学)>]

first()返回符合条件的第一条记录:

school_01 =School.query.first()
print(school_01)# 输出:<School(name:北京大学)>

get()返回指定主键值(id字段)的记录:

school_01 = School.query.get(1)
print(school_01)#输出:<School(name:北京大学)>

filter() 使用指定的规则过滤记录相当于sql的where约束条件,返回新产生的查询对象。

beijing_all = School.query.filter(School.area == "北京").all()
beijing_first = School.query.filter(School.area == "北京").first()
print(beijing_all)
print(beijing_first)# 输出:[<School(name:北京大学)>, <School(name:清华大学)>]
#       <School(name:北京大学)>

filter_by:同filter()效果一样,查询的时候使用关键字参数查询(无法进行多表复杂查询,不推荐使用)

zhongshan_school = School.query.filter_by(name='中山大学').all()
print(zhongshan_school)# 输出:[<School(name:中山大学)>]

db.session.qury(模型类)等价于模型类.query,db.session.qury功能更强大一些,可以进行多表查询。

fudan_school = School.query.filter(School.name == '复旦大学').first()
print(fudan_school)
# 输出:<School(name:复旦大学)>fudan_school = db.session.query(School).filter(School.name == '复旦大学').first()
print(fudan_school)
# 输出:<School(name:复旦大学)>

提示:其他的过滤器会在接下来的章节具体根据实际案例讲解

3.3.3 改

实例3.3.3.1: 修改实例

修改北京大学的录取成绩

beida = School.query.filter(School.name=='北京大学').first()
beida.score = 630
db.session.commit()

更新一条记录分为一下几部:

  1. 找到对应的记录对象

  2. 修改记录对象的属性

  3. 直接调用db.session.commit()提交会话

    提示:只有要插入新的记录或要将现有的记录添加到会话中时才需要使用add()方法。只是更新现有记录的时可以修改记录对象属性后直接提交会话

3.3.4 删

实例3.3.4.1: 删除实例

从数据库中删除清华大学相关信息

qinghua = School.query.filter(School.name=='清华大学').first()
db.session.delete(qinghua)
db.session.commit()


删除一条记录分为以下几步:

  1. 找到对应的记录对象
  2. 需要调用delete()方法在会话中标识需要删除的记录,具体是把该记录对象传入db.session.delete(记录对象)实现标识。
  3. 调用db.session.commit()提交会话。

08_Flask ORM 利用SQLAlchemy进行数据库增删改查相关推荐

  1. django,form表单,数据库增删改查

    Django 02  复习:   Django下载:    在命令行输入:     pip3 install django==1.11.11     在这里不要用最新的3.7,推荐使用3.6/3.5/ ...

  2. IntelliJ Idea SpringBoot 数据库增删改查实例

    . ____ _ __ _ _/\\ / ___'_ __ _ _(_)_ __ __ _ \\\\( ( )\___ | '_ | '_| | '_ \/ _` | \\\\ \\/ ___)| | ...

  3. beego原生mysql查询_go——beego的数据库增删改查

    一直都不理解使用go语言的时候,为什么还要自己去装beego,以为使用go便可以解决所有的问题,结果在朋友的点拨下,才意识到: go与beego的关系就好比是nodejs与thinkjs的关系,因此也 ...

  4. Mybatis实现简单的数据库增删改查操作

    简介: MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Ma ...

  5. 常用的Mybatis-Plus方法,让你的数据库增删改查(CRUD)一键实现

    常用的Mybatis-Plus方法,让你的数据库增删改查(CRUD)一键实现 以下方法全部亲测可用 //测试查找全部@Testpublic void testSelectAll(){List<U ...

  6. Mysql (一)Mysql 数据库增删改查

    mysql数据库增删改查增:create database DBname charset gbk; 删:drop database DBname; 改:alter database DBname ch ...

  7. sql增删改查_快速搞定数据库增删改查|附思维导图

    数据库学习,增删改查一直是测试工程师面试笔试的必考知识点,对于常用sql语法我们一定要牢记于心,尤其是各种查询的用法,在面试的时候,一个小小的知识点,面试官都可以推断出求职者的基础是否扎实. 下面是关 ...

  8. Java+MyEclipse+Tomcat (六)详解Servlet和DAO数据库增删改查操作

    此篇文章主要讲述DAO.Java Bean和Servlet实现操作数据库,把链接数据库.数据库操作.前端界面显示分模块化实现.其中包括数据的CRUD增删改查操作,并通过一个常用的JSP网站前端模板界面 ...

  9. php+mysql+into_PHP+Mysql 如何实现数据库增删改查

    PHP+Mysql实现数据库增删改查的方法:1.创建入口文件[index.html]连接数据库.查询数据:2.点击增加按钮,通过[addnews.html]添加数据:3.点击删除按钮,通过服务端文件[ ...

  10. Java连接Mysql数据库增删改查实现

    Java连接Mysql数据库增删改查实现 时间比较赶,我这里只实现查询,有时间再添加另外两个 难度 : ⭐⭐⭐(全星5颗星的情况下) 新建一个动态的网站工程, 把jar包全部复制进去,主要要那个mys ...

最新文章

  1. Django模型之数据库操作-查询
  2. 带你开发类似 Pokemon Go 的 AR 游戏
  3. iOS开发之UIDevice通知
  4. 通用数据级别权限的框架设计与实现(3)-数据列表的权限过滤
  5. 基于用户的协同过滤和皮尔逊相关系数
  6. 欢迎使用CSDN-markdown编辑器(此为使用指南,自己还不熟练有些功能的使用)
  7. ABAP EXCEL 上传 和下载 过程
  8. HTML中的全局属性
  9. 牛顿-拉夫逊法 原理讲解以及python算例实现
  10. 堆中的路径 (25 分)
  11. CodeForces - 1521D Nastia Plays with a Tree(树上最小路径覆盖)
  12. 你也可以搞懂的微服务第一篇——来自ThoughtWork的学习体验
  13. 清华大学王媛老师的讲座
  14. 027_编写MapReduce的模板类Mapper、Reducer和Driver
  15. python常用代码总结-Python基础常见问题总结(一)
  16. 商业云平台和开源云平台
  17. 从windows向vmware中传输压缩包出现的压缩包异常的问题
  18. C++ atuo关键字的应用 -- 尾置返回类型(trailing return type)
  19. 大数据环境下的智慧教育
  20. 利用python实现对人物头发及衣服颜色的替换

热门文章

  1. 我用 Python 自制成语接龙小游戏,刺激!
  2. 哈哈哈哈,这个勒索软件笑死我了!
  3. 国产操作系统之优麒麟安装
  4. 关于新APP,从交底书入手
  5. matlab水汽计算公式,饱和水汽压的计算
  6. Go 开发关键技术指南 | 带着服务器编程金刚经走进 2020 年(内含超全知识大图)
  7. 2016年计算机基础题库,2016考试计算机基础知识题库
  8. Java过滤器和拦截器的区别
  9. Ip-san 配置过程
  10. matlab gui设置参数,基于Matlab/GUI界面设计的参数在线整定与优化(三)