阅读本文前,需要你对python、Mysql的基本数据类型有所了解,本文介绍了最为基础创建字段,创建表知识,在下篇文章中我会介绍关于增删改查的知识,预计会讲完所有关于外键关联查询重难点
一、安装依赖进行连接
1、安装 flask-sqlalchemy
python
pip install flask-sqlalchemy
2、如果sqlalchemy连接的是 mysql /MariaDB数据库,需要安装 mysqldb 或pymysql驱动
python
pip install flask-mysqldb
3、连接数据库
按照以下配置项,并提前准备好数据库
python
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
class Config(object):
DEBUG = True
# 数据库链接配置 = 数据库名称://登录账号:登录密码@数据库主机IP:数据库访问端口/数据库名称?charset=编码类型
SQLALCHEMY_DATABASE_URI = "mysql://root:123456@127.0.0.1:3306/flaskdemo?charset=utf8mb4"
# 动态追踪修改设置,如未设置只会提示警告
SQLALCHEMY_TRACK_MODIFICATIONS = False
# ORM运行时会显示ORM生成的原始SQL语句[调试]
SQLALCHEMY_ECHO = True
app.config.from_object(Config)
db = SQLAlchemy(app) # 这一步相当于下面两步
# db = SQLALchemy()
# db.init_app(app)
二、定义表结构
1、字段类型
毫无疑问,最最最最最重要的过程便是定义字段,但在学习如何定义字段之前,需要先知道可以定义什么字段? 下表是模型可定义字段类型及对应python数据类型
常用的SQLAlchemy字段类型
标黄为常用模型字段
| 模型字段类型名 | python中数据类型 | 说明 |
|---|---|---|
| Integer | int | 普通整数,一般是32位 |
| SmallInteger | int | 取值范围小的整数,一般是16位 |
| BigInteger | int | 不限制精度的整数 |
| Float | float | 浮点数 |
| Numeric | decimal.Decimal | 普通数值,一般是32位 |
| String | str | 变长字符串 |
| Text | str | 变长字符串,对较长或不限长度的字符串做了优化 |
| Unicode | unicode | 变长Unicode字符串 |
| UnicodeText | unicode | 变长Unicode字符串,对较长或不限长度的字符串做了优化 |
| Boolean | bool | 布尔值 |
| DateTime | datetime.datetime | 日期和时间 |
| Date | datetime.date | 日期 |
| Time | datetime.time | 时间 |
| LargeBinary | bytes | 二进制文件内容 |
| Enum | enum.Enum | 枚举类型,相当于django的choices,但是功能没有choices那么强大 |
2、定义字段
了解完常用字段类型之后,进入定义字段的学习,那我们该用什么定义字段?
答:在 Flask-SQLAlchemy 中,定义模型字段必须使用 db.Column 这是 SQLAlchemy(通过 Flask-SQLAlchemy 封装)的语法要求。
举个例子:
以下模型中的每一行均表示数据库表的一个字段,不难看出,清一色使用 xx = db.Column(db.类型, ......) 定义
python
# 未设置任何约束,不是最终版
class Course(db.Model):
id = db.Column(db.Integer)
name = db.Column(db.String(64))
price = db.Column(db.Numeric(7, 2))
2.1、为什么用 db.Column?
因为:
- db.Column 是 SQLAlchemy 的 列描述符(Column Descriptor)
- 它告诉 SQLAlchemy:"这是一个要映射到数据库表的列"
- 它携带了 数据类型、约束(主键、非空等)、索引、默认值 等元信息
2.2、db.Column 的完整结构
实际开发中,关键字参数不会经常使用, 只有其余三个是我们需要处理的,不要有畏难心理
python
字段名 = db.Column(
数据类型,
*约束或选项,
**关键字参数
)
常见用法:看完你也能照着写出来
|-------------------------------------------------|---------------|
| 写法 | 说明 |
| 不带约束的 | |
| count = db.Column(db.Integer) | 整数列 |
| name = db.Column(db.String(100)) | 最长 100 字符的字符串 |
| bio = db.Column(db.Text) | 长文本 |
| create = db.Column(db.DateTime) | 日期时间 |
| is_active = db.Column(db.Boolean) | 布尔值 |
| 带约束的 | |
| id = db.Column(db.Integer, primary_key=True) | 主键 |
| mobile = db.Column(db.String(11), unique=True) | 唯一约束 |
| name = db.Column(db.String, nullable=False) | 不允许为空 |
| role = db.Column(db.String, default="customer") | 默认值 |
看完上面示例,你肯定可以明白,一个字段,只需要通过 db.Column再加上字段类型 约束即可获得。
2.3、约束
**上面反复提到约束,那么什么是约束呢,**如果你学过数据库表,肯定知道有主键约束,外键约束......,这里说的约束和数据库表的约束是同一回事,那可以在代码里定义什么约束?
常用的SQLAlchemy列约束选项
|-------------|----------------------------------|
| 选项名 | 说明 |
| primary_key | 如果为True,代表当前数据表的主键 |
| unique | 如果为True,为这列创建唯一 索引,代表这列不允许出现重复的值 |
| index | 如果为True,为这列创建普通索引,提高查询效率 |
| nullable | 如果为True,允许有空值,如果为False,不允许有空值 |
| default | 为这列定义默认值 |
3、万能定义模型口诀
step1:构思表结构
建模型前,一定一定要先想清楚表结构!!!
- 列名
- 数据类型
- 是否有约束
step2:查表对应
上述步骤完成后,根据本文给出的两个表格,进行匹配对应。
step3:不断调整
可能step1中,你就构思错了,选错了数据类型......,这都是正常的。及时调整,记录错误
举个例子:
python
我要建一个User模型
需要用到的字段
id ------ 整型 ------ 主键约束
name ------ 字符串类型 ------ 1、用户名不允许重复 (唯一约束)
mobile ------ 字符串类型 ------ 1、手机号不允许重复 (唯一约束)2、能存None值
email ------ 字符串类型 ------ 1、邮箱不允许重复 (唯一约束)2、能存None值
age ------ 整型 (但不能太大)------ 默认值约束
gender ------ 布尔 ------ 默认值约束
def generate_temp_username():
return f"user_{uuid.uuid4().hex[:8]}" # 如 user_a1b2c3d4
class Student(db.Model):
id = db.column(db.Integer, primary_key=True)
name = db.column(db.String(10), unique=True, default=generate_temp_username)
mobile = db.column(db.String(11), unique=True, nullable=True)
email = db.column(db.String(128), unique=True, nullable=True)
age = db.column(db.SmallInteger, default=18)
gender = db.column(db.Boolean, default=True)
三、创建表
1.视图中(了解)
在视图中创建,我们只需要调用 db.create_all()即可,但是实际开发中,我们不会这样
python
import uuid
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
class Config(object):
DEBUG = True
# 数据库链接配置 = 数据库名称://登录账号:登录密码@数据库主机IP:数据库访问端口/数据库名称?charset=编码类型
SQLALCHEMY_DATABASE_URI = "mysql://root:123456@127.0.0.1:3306/flaskdemo?charset=utf8mb4"
# 动态追踪修改设置,如未设置只会提示警告
SQLALCHEMY_TRACK_MODIFICATIONS = False
# ORM运行时会显示ORM生成的原始SQL语句[调试]
SQLALCHEMY_ECHO = True
app.config.from_object(Config)
db = SQLAlchemy(app)
def generate_temp_username():
return f"user_{uuid.uuid4().hex[:8]}" # 如 user_a1b2c3d4
class Student(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(10), unique=True, default=generate_temp_username)
mobile = db.Column(db.String(11), unique=True, nullable=True)
email = db.Column(db.String(128), unique=True, nullable=True)
age = db.Column(db.SmallInteger, default=18)
sex = db.Column(db.Boolean, default=True)
@app.route('/create')
def create():
db.create_all()
return "创建完成"
if __name__ == "__main__":
app.run('0.0.0.0',debug=True)
2、视图外
点入create_all方法,可以看到这句话------意思是,这个方法的调用需要 Flask应用的上下文处于激活状态下。
大白话就是:当前的运行的app可以明确对应是哪个Flask app,如果你还是觉得抽象也不影响你学习创建表

只需将这个操作记住即可,app.app_context()作用在于创建一个Flask app上下文
with app.app_context():
db.create_all()
python
import uuid
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
class Config(object):
DEBUG = True
# 数据库链接配置 = 数据库名称://登录账号:登录密码@数据库主机IP:数据库访问端口/数据库名称?charset=编码类型
SQLALCHEMY_DATABASE_URI = "mysql://root:123456@127.0.0.1:3306/flaskdemo?charset=utf8mb4"
# 动态追踪修改设置,如未设置只会提示警告
SQLALCHEMY_TRACK_MODIFICATIONS = False
# ORM运行时会显示ORM生成的原始SQL语句[调试]
SQLALCHEMY_ECHO = True
......
# 其余代码不变 只是新加这一行,并将数据库表创建方法放入这一行内
with app.app_context():
db.create_all()
......
if __name__ == "__main__":
app.run('0.0.0.0',debug=True)
3、数据库表的表名
3.1、tablename
这里需要讲一个属性 tablename,它定义在模型类中用于控制表名的生成。
特点在于,不管定义什么内容最后得到的一定小写的表名,只要是符合规范的表名
python
class Student(db.Model):
__tablename__ = "DB_Student" # 生成的表名为 db_student
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(10), unique=True, default=generate_temp_username)
mobile = db.Column(db.String(11), unique=True, nullable=True)
email = db.Column(db.String(128), unique=True, nullable=True)
age = db.Column(db.SmallInteger, default=18)
sex = db.Column(db.Boolean, default=True)
3.2、不定义__tablename__
如果不定义__tablename__,此时创建的表名和模型类名有关
- 模型类名为一个单词 ------ 则表名为对应小写 例:Student -> student
- 模型类名为多个单词 ------ 以_连接多个单词转小写 例: MyStudent -> my_student