1.理解ORM

  • ORM是MTV模型里面的Model模型
  • ORM(Object Relational Mapping),对象关系映射
  • 举例:学生选课

学生和课程这两个实体,一个学生可以选择多门课程,一个课程可以被多名学生选择。这两个实体是多对多的关系,学生选课对应的数据库表

为什么要学习ORM

ORM的重要特性

  • 面向对象的编程思想,方便扩充
  • 少写(几乎不写)SQL,提升开发效率
  • 支持多种类型的数据库,方便切换
  • ORM技术成熟,能解决绝大部分问题

2.环境安装

2.1.Flask-sqlalchemy介绍及安装

  • PIP安装: pip install -U Flask-SQLAlchemy
  • 源码安装: python setup.py install
  • 使用国内镜像安装: pip install -U -i https://mirrors.aliyun.com/pypi/simple flask-sqlalchemy

常见安装报错:ERROR: Could not install packages due to an OSError:

解决方案:在pip install 后面加上 --user即可

备注:如果是第一次安装flask-sqlalchemy,还需要安装它数据库的依赖mysqlclient。 pip install mysqlclient

安装mysqlclient常见报错: error: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual C++ Build Tools": https://visualstudio.microsoft.com/downloads/

 解决方案1:https://blog.csdn.net/alicee_2012/article/details/122726986

解决方案2:https://blog.csdn.net/weixin_42403632/article/details/117087559(我的报错是通过这个解决的)

安装成功

2.2.Flask-sqlalchemy配置

3.ORM的CURD操作

3.1.设计数据库模型并创建表

数据库模型设计

  • 1)绑定到Flask对象: db=SQLAlchemy(app)
  • 2)ORM模型创建:

    class User(db.Model):
    id=db.Column(db.Integer,primary_key=True)
  • 3)指定表的名称: __tablename__='weibo_user'

创建和删除表

  • 1)手动创建数据库
  • 2)创建表: >>> db.create_all(bind='db1') #bind='db1'可以不传,当存在需要对多个数据库创建表时,需要添加对应的数据库对象。只有一个库时,不用加
  • 3)删除表: >>> db.drop_all()

实例验证:设计数据库模型,创建/删除表

创建指定名称的表

3.2.数据库模型设计

数据库的表肯定不止一张,同时数据表之间都会有一些关联关系,该如何实现?

  • 通过db.ForeignKey()进行外键关联
  • 通过db.relationship()进行反向引用

 1 from flask import Flask, render_template
2 from flask_sqlalchemy import SQLAlchemy
3
4 app = Flask(__name__)
5 # 配置数据库的连接参数
6 app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:*****@*******/test_flask'
7
8 db = SQLAlchemy(app)
9
10
11 class User(db.Model): #User为模型名称,即类名为模型名称
12 """ 用户的基础信息 """
13 __tablename__ = 'weibo_user'
14 id = db.Column(db.Integer, primary_key=True)
15 username = db.Column(db.String(64), nullable=False)
16 password = db.Column(db.String(256), nullable=False)
17 birth_date = db.Column(db.Date, nullable=True)
18 age = db.Column(db.Integer, default=0)
19
20 class UserAddress(db.Model):
21 """ 用户的地址 """
22 __tablename__ = 'weibo_user_addr'
23 id = db.Column(db.Integer, primary_key=True)
24 addr = db.Column(db.String(256), nullable=False)
25 user_id = db.Column(db.Integer, db.ForeignKey('weibo_user.id'), nullable=False) #使用db.ForeignKey()进行外键关联
26 user = db.relationship('User', backref=db.backref('address', lazy=True)) #这一行代码不会在weibo_user_addr这张表里面增加一列,它的作用就是为了方便我们操作模型的时候去访问去查询
27 # 使用db.relationship()进行反向引用。反向关联谁呢,关联User模型;建立一个反向引用backref=db.backref(),反向引用给谁呢,给address这个名字自己定义,lazy=True就是我们查询到我们用户对象的时候,不直接把他下面所有的地址列表给他查出来,当我们去访问的时候,访问下面地址列表的时候再给他查出来
28
29 '''
30 接着上面代码举个例子进一步解释说明反向引用:
31 UserAddress里面有个反向引用,引用的谁呢,引用的User
32
33 场景一:
34 user = User() #得到某一个用户张三,想知道张三下面所有得地址列表怎么办?
35 user.address #通过user.address就可以获取到到UserAddress这个模型了,就可以找到张三下面得所有地址列表,即地址表内容
36
37 场景二:
38 假设我们查到了某一个地址,也就是UserAddress模型对应数据库的内容
39 addr = UserAddress() #根据地址如何去查用户表的信息呢?
40 addr.user #通过addr.user 就得到了User模型的对象,也就是user表对象
41 '''
42
43
44
45 @app.route('/')
46 def mine():
47 """ 首页 """
48 return render_template('index.html')

3.3.使用ORM插入、修改、删除数据

继续上面代码和用户表、地址表阐述

新增/修改数据

  • 构造ORM模型对象: user = User('admin','admin@example.com') 。在模型类User里面传递一些参数:用户名、密码、用户id等等即user表数据内容,构造一个user对象
  • 添加到db.session,session可以理解为一个会话(备注:session里面可添加多个对象): db.session.add(user) ,可以多次调用add传递多个对象
  • 提交到数据库: db.session.commit ,通过commit就完成了在用户表里面添加一条用户记录

新增数据实例:

修改数据实例:

物理删除数据:数据记录在表中直接删掉

  • 通过query.filter_by()查询ORM模型对象: user=User.query.filter_by(username='王五').first() ,通过query.filter_by找到User模型中用户叫王五的数据,first取第一条
  • 添加到db.session,注意这个地方是delete不是add: db.session.delete(user)
  • 提交变更到数据库: db.session.commit

物理删除数据实例:

逻辑删除:相当于软删除,在表中添加一个状态位,比如isvalid字段,用于标记该记录是否删除(0:删除,1:未删除),其实表中数据记录还在的。

3.4.使用ORM进行数据查询与展示

继续上面代码和用户表、地址表阐述

ORM查询

ORM查询返回的是一个结果集,可以把它看成list。注意:当模型没有使用__tablename__命名表名,那么表名就是模型名即类的名字。

筛选/获取ORM返回结果集:

  • 查询模型(表)所有数据query.all(): User.query.all()
  • 按条件查询
    • query.filter_by(): User.query.filter_by(username='张三')
    • query.filter(): User.query.filter(User.nickname.endswith('五')).all()
    • 可以使用filter()进行一些复杂的查询,:如nickname.endswith() 表中nickname字段是什么结尾的、上面all()是将查询出来的结果全部返回。

对ORM返回结果进行操作:

  • 排序query.order_by(): User.query.order_by(User.username)
  • 查询TOP10的数据 query.limit(): User.query.limit(10).all()

返回单个ORM对象即查询结果只有一条数据

  • 根据主键(primary_key)值查询: User.query.get(1)
  • 获取第一条记录first(): User.query.first()

同时还有一些常用的视图快捷函数:

  • 返回的数据有则返回,无则返回404

    • first()  vs  first_or_404()
    • get()   vs  get_or_404()

  • 多表关联查询

    • 方式一:db.session.query(User).join(Address)
    • 方式二:User.query.join(Address)
  • 分页(offset/limit)
    • 方式一:.offset(offset)
    • 方式二:.limit(limit)
    • offset和limit使用方法和在mysql中使用一致
  • 分页(paginate):query对象提供的paginate函数进行分页。 .paginate(page=2,per_page=4) #page当前在第几页,per_page每一页多少条,返回的是一个Pagination的对象 。返回的Pagination对象拥有的属性和函数如下
    • has_prev/has_next :是否有上一页/下一页
    • items :当前页的数据列表
    • prev_num/next_num :上一页/下一页的页码
    • total :总记录数
    • pages :总页数

paginate实例练习:

1)准备数据

2)分页: list_user.paginate(page2,per_page=4)

3)在模板中实现分页操作

 1 '''***app.py***'''
2
3 from flask import Flask, render_template
4 from flask_sqlalchemy import SQLAlchemy
5
6 app = Flask(__name__)
7 # 配置数据库的连接参数
8 app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:**@******/test_flask'
9 db = SQLAlchemy(app)
10
11
12 class User(db.Model):
13 __tablename__ = 'weibo_user'
14 id = db.Column(db.Integer, primary_key=True)
15 username = db.Column(db.String(64), nullable=False)
16 password = db.Column(db.String(256), nullable=False)
17 birth_date = db.Column(db.Date, nullable=True)
18 age = db.Column(db.Integer, default=0)
19
20
21 class UserAddress(db.Model):
22 """ 用户的地址 """
23 __tablename__ = 'weibo_user_addr'
24 id = db.Column(db.Integer, primary_key=True)
25 addr = db.Column(db.String(256), nullable=False)
26 user_id = db.Column(db.Integer, db.ForeignKey('weibo_user.id'), nullable=False)
27 user = db.relationship('User', backref=db.backref('address', lazy=True))
28
29
30 @app.route('/')
31 def mine():
32 """ 首页 """
33 return render_template('index.html')
34
35
36 @app.route('/user/<int:page>/')
37 def list_user(page):
38 """ 用户分页 """
39 per_page = 10 # 每一页的数据大小
40 # 1. 查询用户信息
41 user_ls = User.query
42 # 2. 准备分页的数据
43 user_page_data = user_ls.paginate(page, per_page=per_page)
44 return render_template('list_user.html', user_page_data=user_page_data)
 1 <!--  ***list_user.html***   -->
2
3 <!DOCTYPE html>
4 <html lang="en">
5 <head>
6 <meta charset="UTF-8">
7 <title>用户分页操作</title>
8 </head>
9 <body>
10 <h3>总共有{{ user_page_data.total }}用户,当前在第{{ user_page_data.page }}页用户, 总共{{ user_page_data.pages }}页</h3>
11 <p>
12 用户列表:
13
14 <ul>
15 {% for user in user_page_data.items %}
16 <li>{{ user.username }} - {{ user.password }}</li>
17 {% endfor %}
18 </ul>
19 {% if user_page_data.has_prev %}
20 <a href="{{ url_for('list_user', page=user_page_data.prev_num) }}">上一页</a>
21 {% endif %}
22 {% if user_page_data.has_next %}
23 <a href="{{ url_for('list_user', page=user_page_data.next_num) }}">下一页</a>
24 {% endif %}
25 </p>
26 </body>
27 </html>

思考:

通过本篇ORM学习,实现了可以将模型数据通过视图传递给模板进行展示。那么模板html如何通过视图对模型中的数据进行增删改查?详见下一篇笔记:Flask表单的实现

Python全栈工程师之从网页搭建入门到Flask全栈项目实战(5) - Flask中的ORM使用的更多相关文章

  1. Python全栈工程师之从网页搭建入门到Flask全栈项目实战(3) - 入门Flask微框架

    1.安装Flask 方式一:使用pip命令安装 pip install flask 方式二:源码安装 python setup.py install 验证 第一个Flask程序 程序解释 参数__na ...

  2. Python全栈工程师之从网页搭建入门到Flask全栈项目实战(1) - ES6标准入门和Flex布局

    1.简述 1.什么是ES6?ES6, 全称 ECMAScript 6.0,是 JavaScript 的下一个版本标准,2015年6月份发版.ES6的主要目的是为了解决 ES5 的先天不足. 2.了解E ...

  3. Web全栈工程师修养

    全栈工程师现在是个很热的话题,如何定义全栈工程师?在著名的问答网站Quora上有人提出了这个问题,其中一个获得了高票的回答是: 全栈工程师是指,一个能处理数据库.服务器.系统工程和客户端的所有工作的工 ...

  4. 阿里巴巴年薪800k大数据全栈工程师成长记

    大数据全栈工程师一词,最早出现于Facebook工程师Calos Bueno的一篇文章 - Full Stack (需fanqiang).他把全栈工程师定义为对性能影响有着深入理解的技术通才.自那以后 ...

  5. Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端

    0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...

  6. EFCodeFirst快速搭建入门

    EFCodeFirst快速搭建入门 1.新建Model类库项目. 添加EntityFramework.dll的引用. 编写实体类Course,Student. namespace EFCodeFirs ...

  7. 测开之Python自动化全栈工程师+性能专项(送思维导图)

    测开之Python自动化全栈工程师+性能专项 功能测试基础 接口测试基础接口的通信原理与本质cookie.session.token详解接口测试的意义与测试方法接口测试用例的设计 app测试 app流 ...

  8. Python全栈工程师(装饰器、模块)

    ParisGabriel                每天坚持手写  一天一篇  决定坚持几年 全栈工程师     Python人工智能从入门到精通 装饰器 decorators(专业提高篇) 装饰 ...

  9. Python全栈工程师(递归函数、闭包)

    ParisGabriel            每天坚持手写  一天一篇  决定坚持几年 全栈工程师     Python人工智能从入门到精通 函数式编程: 是指用一系列函数解决问题 每一个函数完成细 ...

  10. 【目录】python全栈工程师

    第一阶段:Python 语言核心编程1. Python核心   -- 2048 游戏核心算法2. 面向对象   -- 天龙八部游戏技能系统3. Python高级   -- 集成操作框架项目:2048游 ...

随机推荐

  1. 第六章:Django 综合篇 - 3:使用MySQL数据库

    在实际生产环境,Django是不可能使用SQLite这种轻量级的基于文件的数据库作为生产数据库.一般较多的会选择MySQL. 下面介绍一下如何在Django中使用MySQL数据库. 一.安装MySQL ...

  2. windows系统下使用bat脚本文件设置MySQL系统环境变量

    说明:在一个bat文件中设置tomcat环境变量后,不能直接使用,需要另起一个bat文件才能使用 号开头的行不要写在bat文件中 # 这个bat文件实现的功能:设置环境变量 @echo off set ...

  3. [题解] Codeforces 1268 D Invertation in Tournament 结论,兰道定理

    题目 本题需要用到的结论: 一.兰道定理 二.如果\(n\geq4\),那么\(n\)个点的强连通竞赛图存在\(n-1\)个点的强连通子图. 证明: 现在有一个n-1个点的竞赛图(不一定强连通,称其为 ...

  4. .NET 开源项目推荐之 直播控制台解决方案 Macro Deck

    流媒体是一个吸引数亿万玩家的严肃行业. 最受欢迎的游戏锦标赛的转播获得了数百万的观看次数,从商业角度来看,这也使游戏行业变得有趣.在直播圈有个很受欢迎的直播控制台程序Macro Deck, 它是基于A ...

  5. 洛谷P4630 [APIO2018] Duathlon 铁人两项 (圆方树)

    圆方树大致理解:将每个点双看做一个新建的点(方点),该点双内的所有点(圆点)都向新建的点连边,最后形成一棵树,可以给点赋予点权,用以解决相关路径问题. 在本题中,方点点权赋值为该点双的大小,因为两个点 ...

  6. Linux Block模块之deadline调度算法代码解析

    1 总体说明 Deadline调度器对一个请求的多方面特性进行权衡来进行调度,以期望既能满足块设备扇区的顺序访问又能兼顾到一个请求不会在队列中等待太久导致饿死.Deadline调度器为了兼顾这两个方面 ...

  7. python关于Django搭建简单博客项目(详解一)

    上一篇我们说了如何搭建简易博客网站,下面我们来进行详细解答.本文没有特定顺序,请结合上一篇和源代码参照学习. 相关源代码和解析请参看:https://github.com/Cheng0829/mysi ...

  8. Codeforces Round #830 (Div. 2) A-D

    比赛链接 A 题解 知识点:贪心,数论. 先求出序列最大公约数 \(d\) ,如果为 \(1\) 直接输出 \(0\) . 否则,尝试用最后一个数操作, \(gcd(d,n) = 1\) 则可以,花费 ...

  9. OpenMP 入门

    OpenMP 入门 简介 OpenMP 一个非常易用的共享内存的并行编程框架,它提供了一些非常简单易用的API,让编程人员从复杂的并发编程当中释放出来,专注于具体功能的实现.openmp 主要是通过编 ...

  10. POC、EXP、SRC概念厘清

    「POC」 POC可以看成是一段验证的代码,就像是一个证据,能够证明漏洞的真实性,能证明漏洞的存在即可.     https://zhuanlan.zhihu.com/p/26832890 「EXP」 ...