一文掌握在Flask使用SQLAlchemy(上)

阅读本文前,需要你对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:构思表结构

建模型前,一定一定要先想清楚表结构!!!

  1. 列名
  2. 数据类型
  3. 是否有约束

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

四、进阶补充

相关推荐
strayCat232552 小时前
4. Spring Boot 数据持久化(JPA)
java·spring boot·后端
Rabbit_QL2 小时前
[Token实战]Flask JWT 登录接口
后端·python·flask
荧焰2 小时前
Spring定时任务设计
后端
火锅鸡的味道2 小时前
解决AOSP工程Android Studio打开卡顿
android·python·android studio
strayCat232552 小时前
2. Spring Boot 自动配置原理深度解析
java·spring boot·后端
SimonKing2 小时前
每月500 Credits+不限频对话,这款IDEA插件的免费版诚意拉满
java·后端·程序员
我叫黑大帅2 小时前
PHP mysqli 实用开发指南
后端·面试·php
纤纡.2 小时前
从基础 CNN 到优化模型:食品图像分类全流程对比实战
人工智能·python·深度学习
kronos.荒2 小时前
图论之岛屿数量(python)
python·图论