flask使用flask-sqlalchemy操作数据库
Flask 中一般使用 pymysql 或者 flask-sqlalchemy 操作数据库,本案例中使用 flask-sqlalchemy 进行基本的操作
安装
# 虚拟环境需要进入到 venv
$ activate
$ pip install flask-sqlalchemy pymysql
需配置数据库驱动,我使用的是 pymysql,默认驱动为 mysqldb,python3 好像并不支持 pip 安装 mysqldb,pymysql 效率好像也更高一些
连接
uri 格式 dialect+driver://username:password@host:port/database
实例:mysql+pymysql://root:root@localhost:3306/mydatabase
配置
from flask_sqlalchemy import SQLAlchemy
app.config['SQLALCHEMY_DATABASE_URI'] = mysql+pymysql://root:root@localhost:3306/mydatabase
db = SQLAlchemy(app)
发现会有警告信息
可以设置 SQLALCHEMY_TRACK_MODIFICATIONS 为 False
SQLALCHEMY_TRACK_MODIFICATIONS 如果设置成 True (默认情况),Flask-SQLAlchemy 将会追踪对象的修改并且发送信号。这需要额外的内存,如果不必要的可以禁用它。
新建表
支持的字段类型
| 类型 | 说明 |
|---|---|
| Integer | 一个整数 |
| String (size) | 有长度限制的字符串 |
| Text | 一些较长的 unicode 文本 |
| DateTime | 表示为 Python datetime 对象的时间和日期 |
| Float | 存储浮点值 |
| Boolean | 存储布尔值 |
| PickleType | 存储为一个持久化的 Python 对象 |
| LargeBinary | 存储一个任意大的二进制数据 |
class User(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
username = db.Column(db.String(30), nullable=False)
email = db.Column(db.String(30), nullable=False, unique=True)
password = db.Column(db.String(30), nullable=False)
role = db.Column(db.Integer, nullable=False, default=1)
createdDate = db.Column(db.DateTime, default=datetime.now())
class Article(db.Model):
# ...
uid = db.Column(db.Integer, db.ForeignKey('user.id'))
db.create_all()
primary_key 主键
autoincrement 是否自增长
nullable 是否为空
default 默认值,只有在添加数据时如果没给 model 传值,会使用 default 值
server_default 生成表结构时的 字段默认值,只能为 str 类型,其他类型会报错,可用 db.text() 进行包裹,直接使用单引号或者双引号效果应该也是一样的
增删改查
http://www.pythondoc.com/flask-sqlalchemy/api.html
增
user = User(username='admin', email='admin@oyal.ml', password='aaa', role=1)
db.session.add(user)
db.session.commit()
查
user = User.query.filter(User.username == 'admin').first()
print(user.email) # admin@oyal.ml
常用方法:
first() 查询第一条数据
all() 查询所有匹配的数据
first_or_404() 查询不到数据返回 404 页面
get() 暂时没遇到怎么用
改
user = User.query.filter(User.username == 'admin').first()
user.email = 'oyal@qq.com'
db.session.commit()
删
user = User.query.filter(User.username == 'admin').first()
db.session.delete(user)
db.session.commit()
一对多关系
外键 & 关系(ForeignKey & relationship)
如果需要查询文章的作者信息,需要两次查询,先查找文章 uid 再 通过 id 查询作者信息
article = Article.query.filter(Article.title == 'test').first()
print(article.author.username)
user = User.query.filter(User.id == article.uid).first()
可设置 relationship(),映射到 user 表
class Article(db.Model):
# ...
uid = db.Column(db.Integer, db.ForeignKey('user.id'))
author = db.relationship('User', backref=db.backref('articles'))
给 Article 模型添加一个 author 属性,可以通过个属性访问作者信息
backref 代表反向引用,可以通过 User.articles 查询这个模型所写的所有文章
article = Article.query.filter(Article.title == 'test').first()
print(article.author.username) # admin
查询作者所有文章可以使用
user = User.query.filter(User.id == '1').first()
print(user.articles) # [<Article 1>, <Article 2>]
for article in user.articles:
print(article.title) # test、test2
拆分 app 和 model
为了解决循环引用需要创建 db.py 新建数据库实例
- 目录结构
.
├── app.py
├── db.py
├── models.py
- db.py
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
- models.py
from db import db
from datetime import datetime
class User(db.Model):
# ...
- app.py
from db import db
from models import User
db.init_app(app)
db.create_all(app=app)
扩展
mysql 中的默认时间值
mysql 中 timestamp 类型可设置两种默认值
CURRENT_TIMESTAMP :当我更新这条记录的时候,这条记录的这个字段不会改变
CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP :当我更新这条记录的时候,这条记录的这个字段将会改变
所以可对以下字段设置
from datet
class Article(db.Model):
# ...
createdDate = db.Column(db.DateTime, nullable=False, default=datetime.now(), server_default=db.text('CURRENT_TIMESTAMP'))
updatedDate = db.Column(db.DateTime, nullable=False, default=datetime.now(), server_default=db.text('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'))
在 sqlalchemy 上看到使用 onupdate 设置更新时间
import datetime
t = Table("mytable", metadata_obj,
Column('id', Integer, primary_key=True),
# define 'last_updated' to be populated with datetime.now()
Column('last_updated', DateTime, onupdate=datetime.datetime.now),
)
default & server_default
使用 server_default 前的表结构
| Field | Type | Null | Key | Default | Extra |
|---|---|---|---|---|---|
| id | int | NO | PRI | NULL | auto_increment |
| username | varchar(30) | NO | NULL | ||
| varchar(30) | NO | UNI | NULL | ||
| password | varchar(30) | NO | NULL | ||
| role | int | NO | NULL | ||
| createdDate | datetime | NO | NULL |
使用 server_default 后的表结构
| Field | Type | Null | Key | Default | Extra |
|---|---|---|---|---|---|
| id | int | NO | PRI | NULL | auto_increment |
| username | varchar(30) | NO | NULL | ||
| varchar(30) | NO | UNI | NULL | ||
| password | varchar(30) | NO | NULL | ||
| role | int | NO | 1 | ||
| createdDate | datetime | NO | CURRENT_TIMESTAMP | DEFAULT_GENERATED |
这篇文章给我提供了很大的帮助 sqlalchemy中Column的默认值属性,非常感谢作者

浙公网安备 33010602011771号