当前位置: 首页 > news >正文

Flask入门教程——李辉 第5章: 数据库 关键知识梳理

文章目录

  • 第5章: 数据库 关键知识梳理
    • 写在前边
      • 扩展了解
    • 使用 SQLAlchemy操作数据库
      • 安装Flask-SQLAlchemy
      • 配置连接数据库
        • 扩展了解
      • 创建数据库模型
        • 常用字段类型
        • 常用字段约束配置
      • 创建数据库表
        • 命令实现
          • 扩展了解
        • 代码实现
      • 对数据库表进行(增、删、改、查)
        • 增(添加)
        • 删(除)
        • 改(修改)
        • 查(读取/查找)
          • 常用的过滤方法
          • 常用的查找方法
        • 扩展
      • 程序操作数据库
        • 首页读取 数据库数据
        • 生成虚拟数据
          • 生成虚拟数据的命令函数
    • 最终 修改俩文件
      • app.py
      • `index.html`

第5章: 数据库 关键知识梳理

写在前边

这个篇文章是基于前三章 内容的,基础的建议 专栏从头看起
笔者学习该书的环境是:

  • 系统:Fedora Linux 42 (Workstation Edition)
  • IDE: vscode
  • Python:3.13.X
  • Conda: conda 25.7.0
  • pip: pip 25.2
  • 第三方库 : 最新

Flask作为Python Web的后端框架,也需要履行后端的核心职责之一——与数据库进行交互

Flask-SQLAlchemy是Flask的第三方扩展,用来简化FlaskSQLAlchemy的操作

SQLite 是一个软件库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎

扩展了解

数据库管理系统(DMS)

关系数据库管理系统(RDMS)

使用 SQLAlchemy操作数据库

安装Flask-SQLAlchemy

pip3 install flask-sqlalchemy

初始操作

from flask import Flask
from flask_sqlalchemy import SQLAlchemy # 导入扩展类app = Flask(__name__)# 初始化扩展 传入程序实例
db = SQLAlchemy(app)

配置连接数据库

  • 配置数据库连接地址 => SQLALCHEMY_DATABASE_URI
  • 对模型修改的检测(可选) => SQLALCHEMY_TRACK_MODIFICATIONS

app_db_connect.py:数据库配置

import os
from flask import Flask
from flask_sqlalchemy import SQLAlchemy # 导入扩展类app = Flask(__name__)# 添加数据库URl 为当前路径下的data.db sqlite 文件
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(app.root_path,'data.db')# 关闭对模型修改的监控
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False# 初始化扩展 传入程序实例
db = SQLAlchemy(app)
扩展了解

Flask-SQLAlchemy文档的配置

Flask文档配置

DB Browser for SQLite 一款 连接SQLite的工具
DB Browser for SQLite 下载

创建数据库模型

借助SQLAIchemy你可以通过定义Python类来表示数据库里的一张表(类属性表示表中的字段/列),通过对这个类进行各种操作来代替SQL语句。这个类我们称之为模型类,类中的属性我们将称之为字段

模型类编写核心:

  1. 模型类要继承db.Model
  2. 字段要实例化db.Column 传入的参数为 字段的类型
  3. 字段约束配置传入额外参数如primary_key`

app_create_db_model.py创建数据库模型:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import osapp = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] ='sqlite:////' + os.path.join(app.root_path,'data.db')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)class User(db.Model):"""生成User表:param db: 数据库模型"""id = db.Column(db.Integer,primary_key=True)name  = db.Column(db.String(20))class Movie(db.Model):"""生成电影数据:param db: 数据库模型"""id = db.Column(db.Integer,primary_key=True)title = db.Column(db.String(60))year = db.Column(db.String(4))
常用字段类型
字段类说明
Integer整型
String(size)字符串,size 为最大长度,比如 db.String(20)
Text长文本
DateTime时间日期,Python datetime 对象
Float浮点数
Boolean布尔值
常用字段约束配置
约束选项说明
primary_key=True设置为主键
unique=True唯一约束(列值不可重复)
index=True创建索引(提升查询效率)
nullable=False非空约束(默认允许NULL)
default=值默认值(支持函数如datetime.now

创建数据库表

声明:如下代码块中带有>>>的是在flask shell中执行,否则就在终端对话框中执行

命令实现

注意app.pyapp_create_db_model.py

flask shell

注意:这里在vscode IDE终端 中可以补全

>>> from app import db
>>> db.create_all()

注意:需要重新生成数据库文件或表模式

>>> db.drop_all()
>>> db.create_all()
扩展了解

数据库迁移工具 Alembic

代码实现

app_initdb.py 使用时将其修改为app.py

"""注意需要在终端执行flask initdb命令来创建数据库文件"""from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import click
import osapp = Flask(__name__)app.config['SQLALCHEMY_DATABASE_URI'] ='sqlite:////' + os.path.join(app.root_path,'data.db')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = Falsedb = SQLAlchemy(app)@app.cli.command()
@click.option('--drop',is_flag=True, help="Create after drop.")def initdb(drop):"""Initialize the database."""if drop:db.drop_all()db.create_all()click.echo('Initialized the database.')

终端执行

flask initdb

重新创建

flask initdb --drop

对数据库表进行(增、删、改、查)

app.py

# coding = utf-8
from flask import Flask,render_template
from flask_sqlalchemy import SQLAlchemy
import click
import osapp = Flask(__name__)app.config['SQLALCHEMY_DATABASE_URI'] ='sqlite:///' + os.path.join(app.root_path,'data.db')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = Falsedb = SQLAlchemy(app)class User(db.Model):"""生成User表:param db: 数据库模型"""id = db.Column(db.Integer,primary_key=True)name  = db.Column(db.String(20))class Movie(db.Model):"""生成电影数据:param db: 电影数据模型"""id = db.Column(db.Integer,primary_key=True)title = db.Column(db.String(60))year = db.Column(db.String(4))@app.cli.command()
@click.option('--drop',is_flag=True, help="Create after drop.")def initdb(drop):"""初始化数据库表"""if drop:db.drop_all()db.create_all()click.echo('Initialized the database.')@app.route("/")
def index():user =  User.query.first()movies = Movie.query.all()return render_template("index.html",user=user,movies=movies)app.run("127.0.0.1",5000,False)
增(添加)
>>> from app import User,Movie 
>>> user = User(name="开心-开心急了")
>>> m1 = Movie(title="Leon",year="1994")
>>> m2 = Movie(title="Mahjong",year="1996")
>>> db.session.add(user)
>>> db.session.add(m1)
>>> db.session.add(m2)
>>> db.session.commit()

注意

  1. 在实例化模型时SQLAlchemy会自动处理id字段。
  2. db.session.commit() 才会真的提交db.session.add(user) 是添加到缓存里(这不是有点像gitee吗)
删(除)

删除id为1的记录

>>> movie = Movie.query.get(1)
>>> db.session.delete(movie)
>>> db.session.delete()
>>> db.session.commit()
改(修改)

id2的修改

>>> movie = Movie.query.get(2)
>>> movie.title = 'WALL-E'
>>> movie.year = '2008'
>>> db.session.commit()
查(读取/查找)

通用的调用方法

<模型类>.query.<过滤方法(可选)>.<查询方法>
>>> from app import Movie
>>> movie = Movie.query.first()  # 获取 Movie 模型的第一个记录(返回模型类实例)
>>> movie.title  # 对返回的模型类实例调用属性即可获取记录的各字段数据
'Leon'
>>> movie.year
'1994'
>>> Movie.query.all()  # 获取 Movie 模型的所有记录,返回包含多个模型类实例的列表
[<Movie 1>, <Movie 2>]
>>> Movie.query.count()  # 获取 Movie 模型所有记录的数量
2
>>> Movie.query.get(1)  # 获取主键(id)值为 1 的记录
<Movie 1>
>>> Movie.query.filter_by(title='Mahjong').first()  # 获取 title 字段值为 Mahjong 的记录
<Movie 2>
>>> Movie.query.filter(Movie.title=='Mahjong').first()  # 等同于上面的查询,但使用不同的过滤方法
<Movie 2>
常用的过滤方法
过滤方法说明
filter()使用指定的规则过滤记录,返回新产生的查询对象
filter_by()使用指定规则过滤记录(以关键字表达式的形式),返回新产生的查询对象
order_by()根据指定条件对记录进行排序,返回新产生的查询对象
group_by()根据指定条件对记录进行分组,返回新产生的查询对象
常用的查找方法
查询方法说明
all()返回包含所有查询记录的列表
first()返回查询的第一条记录,如果未找到,则返回 None
get(id)传入主键值作为参数,返回指定主键值的记录,如果未找到,则返回 None
count()返回查询结果的数量
first_or_404()返回查询的第一条记录,如果未找到,则返回 404 错误响应
get_or_404(id)传入主键值作为参数,返回指定主键值的记录,如果未找到,则返回 404 错误响应
paginate()返回一个 Pagination 对象,可以对记录进行分页处理
扩展

更多数据库操作方法(Query API)

程序操作数据库

首页读取 数据库数据

修改app.py中的

@app.route("/")
def index():return render_template("index.html",name=name,movies=movies)

修改结果对数据库表进行增、删、改、查app.py

修改 index.html name修改为 user.name

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>{{ user.name }}'s Watchlist</title><link rel="icon" href="{{ url_for('static',filename='dicos.ico')}}"><link rel="stylesheet" href="{{url_for( 'static', filename='style.css') }}" type="text/css">
</head>
<body><h2><img src="{{ url_for('static',filename='images/avatar.png')}}" alt="Avatar" class="avatar">{{ user.name }}'s Watchlist</h2>{# 使用 length 过滤器获取 movies 变量的长度 #}<ul class="movie-list">{% for movie in movies %} {# 迭代movies 变量 #}<li>{{ movie.title }} - {{ movie.year }}{# 等同于 movie['title'] #}{% endfor %} {# 不要忘记endfor 来结束for语句 #}</li></ul><img src="{{ url_for('static',filename='images/totoro.gif')}}" alt="totoro" class="totoro"><footer><small>&copy; 2018 <a href="http://helloflask.com/tutorial">HelloFlask</a></small></footer>
</body>
</html>
生成虚拟数据

借助faker快速生成虚拟数据

生成虚拟数据的命令函数
"""注意需要在终端执行flask forge命令来创建数据库文件"""from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import click
import osapp = Flask(__name__)app.config['SQLALCHEMY_DATABASE_URI'] ='sqlite:////' + os.path.join(app.root_path,'data.db')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = Falsedb = SQLAlchemy(app)class User(db.Model):"""生成User表:param db: 数据库模型"""id = db.Column(db.Integer,primary_key=True)name  = db.Column(db.String(20))class Movie(db.Model):"""生成电影数据:param db: 电影数据模型"""id = db.Column(db.Integer,primary_key=True)title = db.Column(db.String(60))year = db.Column(db.String(4))@app.cli.command()
def forge():"""创建虚拟 数据"""name = "开心开心-急了"movies = [{'title': '实现研究而且.', 'year': '1997'}, {'title': '重要出来不要不要广告.', 'year': '1987'},{'title': '活动这些城市.', 'year': '1995'},{'title': '历史网上你的来源选择销售没有.', 'year': '2006'},{'title': '这样简介个人如果信息怎么类型.', 'year': '2024'}, {'title': '能够时候两个.', 'year': '2004'}, {'title': '部分有限电影不要得到应用.', 'year': '2022'}, {'title': '设备处理最后大学为了.', 'year': '1996'}, {'title': '来自谢谢决定.', 'year': '2021'},{'title': '提供所以大家您的非常以后有关.', 'year': '2016'}]# 将用户添加到 会话(session)中user = User(name=name)db.session.add(user)# 将电影名和电影年份 添加到 会话(session)中for m in movies:movie = Movie(title= m['title'],year=m['year'])db.session.add(movie)# 提交 会话(session) 里的修改db.session.commit()click.echo("创建虚拟数据 成功")

执行

flask forge

最终 修改俩文件

app.py

# coding = utf-8
from flask import Flask,render_template
from flask_sqlalchemy import SQLAlchemy
import click
import osapp = Flask(__name__)app.config['SQLALCHEMY_DATABASE_URI'] ='sqlite:///' + os.path.join(app.root_path,'data.db')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = Falsedb = SQLAlchemy(app)class User(db.Model):"""生成User表:param db: 数据库模型"""id = db.Column(db.Integer,primary_key=True)name  = db.Column(db.String(20))class Movie(db.Model):"""生成电影数据:param db: 电影数据模型"""id = db.Column(db.Integer,primary_key=True)title = db.Column(db.String(60))year = db.Column(db.String(4))@app.cli.command()
@click.option('--drop',is_flag=True, help="Create after drop.")def initdb(drop):"""初始化数据库表"""if drop:db.drop_all()db.create_all()click.echo('Initialized the database.')@app.cli.command()
def forge():"""创建虚拟 数据"""name = "开心开心-急了"movies = [{'title': '实现研究而且.', 'year': '1997'}, {'title': '重要出来不要不要广告.', 'year': '1987'},{'title': '活动这些城市.', 'year': '1995'},{'title': '历史网上你的来源选择销售没有.', 'year': '2006'},{'title': '这样简介个人如果信息怎么类型.', 'year': '2024'}, {'title': '能够时候两个.', 'year': '2004'}, {'title': '部分有限电影不要得到应用.', 'year': '2022'}, {'title': '设备处理最后大学为了.', 'year': '1996'}, {'title': '来自谢谢决定.', 'year': '2021'},{'title': '提供所以大家您的非常以后有关.', 'year': '2016'}]# 将用户添加到 会话(session)中user = User(name=name)db.session.add(user)# 将电影名和电影年份 添加到 会话(session)中for m in movies:movie = Movie(title= m['title'],year=m['year'])db.session.add(movie)# 提交 会话(session) 里的修改db.session.commit()click.echo("创建虚拟数据 成功")@app.route("/")
def index():user =  User.query.first()movies = Movie.query.all()return render_template("index.html",user=user,movies=movies)app.run("127.0.0.1",5000,False)

index.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>{{ user.name }}'s Watchlist</title><link rel="icon" href="{{ url_for('static',filename='dicos.ico')}}"><link rel="stylesheet" href="{{url_for( 'static', filename='style.css') }}" type="text/css">
</head>
<body><h2><img src="{{ url_for('static',filename='images/avatar.png')}}" alt="Avatar" class="avatar">{{ user.name }}'s Watchlist</h2>{# 使用 length 过滤器获取 movies 变量的长度 #}<ul class="movie-list">{% for movie in movies %} {# 迭代movies 变量 #}<li>{{ movie.title }} - {{ movie.year }}{# 等同于 movie['title'] #}{% endfor %} {# 不要忘记endfor 来结束for语句 #}</li></ul><img src="{{ url_for('static',filename='images/totoro.gif')}}" alt="totoro" class="totoro"><footer><small>&copy; 2018 <a href="http://helloflask.com/tutorial">HelloFlask</a></small></footer>
</body>
</html>
http://www.dtcms.com/a/525330.html

相关文章:

  • 嘉峪关市建设局建管科资质网站网站制作教程
  • 如何免费建设网站列表页面设计模板
  • 通过diskpart强制格式化报错:虚拟磁盘服务错误:卷大小太大
  • 02)PB(PowerBuilder9)学习 连接数据库 开发一个增删改查功能
  • Java 开发 - 扁平化数据转换成树形结构数据(递归查找 + 移除节点、Map + 一次遍历)
  • 探寻企业数字化转型“底座”:技术基石与核心支撑
  • 做网站视频教学最简单的出入库管理软件
  • [MySQL]表——改变数据
  • 第十一篇《IPv4的救星:初识IPv6的地址格式与优势》
  • 好的网站推荐住房和城乡建设部网站施工员证
  • C++开发之责任链模式
  • JVM面试(内存结构,垃圾回收,类载机制)
  • 并发编程案例分析——高性能限流器Guava RateLimiter(四十六)
  • 灵巧手——faive_gym
  • 亚马逊电子配件类目流量瓶颈突破:DeepBI智能优化策略助力流量增长
  • 桂市做网站的朋友自建电商网站有哪些
  • autoware源码编译
  • react nextjs 项目部署
  • 怎样建设网站 需要哪些条件免费的免抠图素材网站
  • FPGA学习笔记——用Vitis IDE生成工程(串口发送)
  • 烟台 o2o平台带动做网站行业平潭综合实验区交通与建设网站
  • GaussianShader
  • 昆山企业做网站好用的网站系统
  • javaScript事件委托
  • 广州营销型网站建设哪家好公司域名怎么起
  • 28.C++的IO流
  • 车载基础软件——基础软件验证平台典型案例(通信相关)
  • 【FPGA】设计流程——板级验证
  • 1Panel-1Panel中openresty网站目录更改为宿主机共享目录
  • 分支和循环语句