数据库是一个网站的基础。Flask可以使用很多种数据库。比如MySQL,MongoDB,SQLite,PostgreSQL等。这里我们以MySQL为例进行讲解。而在Flask中,如果想要操作数据库,我们可以使用ORM来操作数据库,使用ORM操作数据库将变得非常简单。
在讲解Flask中的数据库操作之前,先确保你已经安装了以下软件:
下面的代码可以实现SQLAlchemy连接数据库,
from sqlalchemy import create_engine
# 数据库的配置变量
HOSTNAME = '127.0.0.1' # 主机名
PORT = '3306' # 端口号
USERNAME = 'root' # 用户名
PASSWORD = '******' # 密码
DATABASE = 'test' # 数据库名称
DB_URL = 'mysql+pymysql://{}:{}@{}:{}/{}'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)
# 创建数据库引擎
engine = create_engine(DB_URL)
# 创建链接
with engine.connect() as con:
rs = con.execute('SELECT 1')
print(re.fetchone())
首先从sqlalchemy中导入create_engine,用这个函数来创建引擎,然后用engine.connect()来连接数据库。其中一个比较重要的一点是,通过create_engine函数的时候,需要传递一个满足某种格式的字符串,对这个字符串的格式来进行解释,
dialect+driver://username:password@host:port/database?charset=utf8
dialect是数据库的实现,比如MySQL、PostgreSQL、SQLite,并且转换成小写。driver是Python对应的驱动,如果不指定,会选择默认的驱动,比如MySQL的默认驱动是MySQLdb。username是连接数据库的用户名,password是连接数据库的密码,host是连接数据库的域名,port是数据库监听的端口号,database是连接哪个数据库的名字。
如果以上输出了1,说明SQLAlchemy能成功连接到数据库。
若要使用SQLAlchemy执行原生SQL,我们只需使用execute()函数即可实现。
我们将上一个例子中的数据库配置选项单独放在一个constants.py的文件中,看以下例子:
from sqlalchemy import create_engine
from constants import DB_URI # 导入解释字符
#连接数据库
engine = create_engine(DB_URI,echo=True)
# 使用with语句连接数据库,如果发生异常会被捕获
with engine.connect() as con:
# 先删除users表
con.execute('drop table if exists authors')
# 创建一个users表,有自增长的id和name
con.execute('create table authors(id int primary key auto_increment,'name varchar(25))')
# 插入两条数据到表中
con.execute('insert into persons(name) values("abc")')
con.execute('insert into persons(name) values("xiaotuo")')
# 执行查询操作
results = con.execute('select * from persons')
# 从查找的结果中遍历
for result in results:
print(result)
ORM(Object Relationship Mapping)模型是对象模型与数据库表的映射,在python中的表现形式是一个类,这个类对应着数据库中的一个数据表;这个类的每一个属性对应数据表中的一个字段。
以下是创建ORM模型的过程,
from sqlalchemy import create_engine
from sqlalchemy import Column, String, Integer, Enum, DateTime # 导入属性
from sqlalchemy.dialects.mysql import LONGTEXT # 导入长文本类型
from sqlalchemy.ext.declarative import declarative_base # 导入库
import enum # 导入枚举模块
from datetime import datetime # 导入时间模块
HOSTNAME = '127.0.0.1' # 数据库地址
PORT = '3306' # 端口号
DATABASE = 'test' # 数据库名
USERNAME = 'root' # 用户名
PASSWORD = '******' # 密码
DB_URI = 'mysql+pymysql://{}:{}@{}:{}/{}'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)
engine = create_engine(DB_URI)
Base = declarative_base(engine) # 创建Base基类
class Hobby(enum.Enum): # 定义一个枚举类
h1 = "抽烟"
h2 = "喝酒"
h3 = "烫头"
class Student(Base): # 用Base类作为基类来写自己的ORM类
__tablename__ = "student" # 表名
# 创建属性来映射到表中的字段,所有需要映射到表中的属性都应该为Column类型
# 在这个ORM模型中创建一些属性,来跟表中的字段进行一一映射。这些属性必须是sqlalchemy给我们提供好的数据类型。
name = Column(String(10), primary_key=True, nullable=False)
sid = Column(Integer)
age = Column(Integer)
hobby = Column(Enum(Hobby))
native_language = Column(Enum("中文", "英文"))
score = Column(Integer)
create_time = Column(DateTime, onupdate=datetime.now, default=datetime.now)
introduce = Column(LONGTEXT)
Base.metadata.create_all() # 将模型映射到数据库中
注意,一旦使用了Base.metadata.create_all()将模型映射到数据库中后,即使改变了模型的字段,也不会重新映射了。
若想要重新映射,必须在Base.metadata.create_all()之前,先执行Base.metadata.drop_all()删除掉ORM模型。
数据类型 | 解释 |
---|---|
Integer | 整形,映射到数据库中是int类型 |
Float | 浮点类型,映射到数据库中是float类型,占据32位 |
Double | 双精度浮点类型,映射到数据库中是double类型,占据64位 |
String | 可变字符类型,映射到数据库中是varchar类型,需要指定长度 |
Boolean | 布尔类型,映射到数据库中的是tinyint类型 |
DECIMAL | 定点类型,这个类型使用的时候需要传递两个参数,第一个参数是用来标记这个字段总能能存储多少个数字,第二个参数表示小数点后有多少位 |
Enum | 指定某个字段只能是枚举中指定的几个值,不能为其他值 |
Date | 存储时间,只能存储年月日。映射到数据库中是date类型。在Python代码中,可以使用datetime.date来指定 |
DateTime | 存储时间,可以存储年月日时分秒毫秒等。映射到数据库中也是datetime类型。在Python代码中,可以使用datetime.datetime来指定 |
Time | 存储时间,可以存储时分秒。映射到数据库中也是time类型。在Python代码中,可以使用datetime.time来至此那个 |
Text | 存储长字符串。一般可以存储6W多个字符。如果超出了这个范围,可以使用LONGTEXT类型。映射到数据库中就是text类型 |
LONGTEXT | 长文本类型,映射到数据库中是longtext类型 |
Column常见参数 | 功能 |
---|---|
primary_key | 设置某个字段为主键 |
autoincrement | 设置这个字段为自动增长的 |
default | 设置某个字段的默认值。在发表时间这些字段上面经常用 |
nullable | 指定某个字段是否为空。默认值是True,就是可以为空 |
unique | 指定某个字段的值是否唯一。默认是False |
onupdate | 在数据更新的时候会调用这个参数指定的值或者函数。在第一次插入这条数据的时候,不会用onupdate的值,只会使用default的值。常用的就是update_time(每次更新数据的时候都要更新的值) |
name | 指定ORM模型中某个属性映射到表中的字段名。如果不指定,那么会使用这个属性的名字来作为字段名。如果指定了,就会使用指定的这个值作为参数。这个参数也可以当作位置参数,在第1个参数来指定 |