Flask 中用 SQLAlchemy 操作数据库
约 217 个字 75 行代码 预计阅读时间 2 分钟
安装包
集成
以 MySQL 为例(使用 pymysql):
配置类 |
---|
| class FlaskPlaygroundConfig:
SQLALCHEMY_DATABASE_URI = f"mysql+pymysql://用户名:密码@地址:端口号/数据库名?charset=utf8mb4"
# 如密码有特殊字符,可用 urllib.parse.quote_plus('密码') 替代
|
ext.py |
---|
| from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
|
app.py |
---|
| app = Flask(__name__)
app.config.from_object(FlaskPlaygroundConfig)
db.init_app(app)
# 测试连接
with app.app_context():
with db.engine.connect() as conn:
result = conn.execute(text('select 1;'))
print('Database connection successful: ', result.fetchone())
|
定义表结构
| class UserEntity(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
create_time = db.Column(db.DateTime, default=datetime.now)
create_user = db.Column(db.Integer, default=0)
is_deleted = db.Column(db.Boolean, default=False)
username = db.Column(db.String(20), unique=True)
nickname = db.Column(db.String(20), nullable=False, default='Default Nickname')
class RouteEntity(db.Model):
__tablename__ = 'routes'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
create_time = db.Column(db.DateTime, default=datetime.now)
create_user = db.Column(db.Integer, db.ForeignKey('users.id'), default=0) # 外键,填表名
# 关联表,此例中关联了 users 表,与定义了外键的 create_user 对应
# UserEntity 实例可以通过 user_entity_instance.routes 属性访问自己创建的线路信息
# RouteEntity 实例可以通过 route_entity_instance.user 属性访问 create_user 的用户信息
user = db.relationship('UserEntity', backref=db.backref('routes'))
class RoutePointEntity(db.Model):
__tablename__ = 'route_points'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
create_time = db.Column(db.DateTime, default=datetime.now)
create_user = db.Column(db.Integer, default=0)
route_id = db.Column(db.Integer, db.ForeignKey('routes.id'), nullable=False)
longitude = db.Column(db.Numeric(10, 7), nullable=False)
latitude = db.Column(db.Numeric(10, 7), nullable=False)
memo = db.Column(db.Text)
parent_route = db.relationship('RouteEntity', backref=db.backref('points'))
|
如果在主程序中添加:
app.py |
---|
| with app.app_context():
db.create_all()
|
理论上会创建不存在的数据表。不会更改已有的数据表。
Warning
实测,似乎不会立即新增,但不影响写入内容,写入内容后就有表结构了。
CRUD
新增
| user = UserEntity(username=username, nickname=nickname)
db.session.add(user)
db.session.commit() # 所有更改操作都要提交后才生效
|
此后可通过 user.id
得知新增的列的 ID。
涉及到关联表的也会一并新增:
| route_points = [RoutePointEntity(...), ...]
route = RouteEntity(points = route_points, ...)
db.session.add(route) # 会一并新增路线和对应的点
db.session.commit()
|
查询
| # 查询 ID = 1 的用户信息
UserEntity.query.get(1)
# 查询给定 ID,未删除的第一条用户信息
UserEntity.query.filter_by(id=user_id, is_deleted=False).first()
# 查询给定路线 ID,未删除的全部路线点信息
db.session.query(RoutePointEntity).filter(RoutePointEntity.route_id == route_entity_bare.id, RoutePointEntity.is_deleted == False).all()
|
其中 UserEntity.query
可视为 db.session.query(UserEntity)
。
如果没有,则返回 None
。
修改
对查询到的实体直接修改属性,提交即可。
| user = UserEntity.query.filter_by(id=user_id, is_deleted=False).first()
user.password = new_password
user.update_time = datetime.now()
db.session.commit()
|
删除
| user = UserEntity.query.filter_by(id=user_id, is_deleted=False).first()
db.session.delete(user)
db.session.commit()
|
很少用,因为现在基本上要求软删除。
注意事项