Python Flask SQLAlchemy 一部分使用

在作项目的过程当中,咱们都遇到过,常常须要修改咱们数据库的字段,在flask中,是经过ORM(对象关系映射)来建立数据库的,表—>model class,字段---->属性python

在flask中,咱们是经过第三方插件SQLAlchemy来建立数据库表,采用的是db.create_all()方法,这样,在咱们修改数据库的Model的字段以后,想要同步数据库,就只能经过删除表,而后从新调用db.create_all()来完成。

因此,flask引入了flask_script 和 flask_migrate(pip install)来解决这个问题:

一. 新建db_init.py 文件, 初始化db
from flask_sqlalchemy import SQLAlchemy
# 初始化db
db = SQLAlchemy()
二. flask app.py文件中使用db
from db_init import db
# db中激活app
db.init_app(app)
with app.app_context():
    # 创建表结构
    db.create_all()
三. 新建manager.py文件,编写以下:app
from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand
from app import create_app
from db_init import db
from models import user, finance_item
# 初始化app
app = create_app()  
manager = Manager(app)
# 要使用flask-migrate,必须先绑定db和app
Migrate(app, db)
# 将MigrateCommand添加到manager中,"db"是自定义命令
manager.add_command('db', MigrateCommand)
# 参考文章
# http://www.javashuo.com/article/p-xmqzgplm-hw.html
# https://blog.csdn.net/weixin_42289273/article/details/116526030
if __name__ == '__main__':
    manager.run()
四. 环境中激活, 迁移, 更新数据库

项目更目录下, 进入terminal, 输入以下命令

python manager.py db init
# 成功后, 在项目目录中会多出一个migration 的文件夹
# 迁移数据库, 这里可以做到数据表字段的增加删除等等
python manager.py db migrate
# 迁移后, 做更新操作
python manager.py db upgrade
五. SQLAlchemy Model的书写
import datetime
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from db_init import db
class BaseDB:
    """
    数据基础类
    """
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    create_time = db.Column(db.DATETIME(6), default=datetime.datetime.now)
    update_time = db.Column(db.DATETIME(6), default=datetime.datetime.now, onupdate=datetime.datetime.now)
    # 是否被删除
    is_delete = db.Column(db.BOOLEAN, default=False)
六. 单个Model的操作

在码脚本过程中, 发现操作数据库的时候, 接口需要写部分高度重复的代码, 试着写了通用的方法, 在接口简单数据库操作, 使用到的时候, 只传入对应的Model name, 就能做单表的增删改查.

# encoding:utf-8
# author: kyleyao
from flask import current_app
from sqlalchemy.exc import IntegrityError
from db_init import db


class DBOperation:

    @staticmethod
    def find_all(model_name) -> list:
        """
        根据提供的数据库表model name查询所有的数据.
        :param model_name: 数据库表名称
        :return:
        """
        items = None
        try:
            items = model_name.query.all()
        except IntegrityError as e:
            current_app.logger.error("got IntegrityError db error please check")
            current_app.logger.error(e)
        except Exception as e:
            current_app.logger.error("got other db error please check")
            current_app.logger.error(e)
        finally:
            return items

    @staticmethod
    def find_items_by(model_name, **kwargs) -> list:
        """
        根据提供的数据库表model name, 以及查询条件, 查询所有匹配的数据.
        :param model_name: 数据库表名称
        :param kwargs: 查询字段 where id = 1, name = abc
        :return: 一个 sqlalchemy model list
        """
        items = None
        try:
            items = model_name.query.filter_by(**kwargs).all()
        except IntegrityError as e:
            current_app.logger.error("got IntegrityError db error please check")
            current_app.logger.error(e)
        except Exception as e:
            current_app.logger.error("got other db error please check")
            current_app.logger.error(e)
        finally:
            return items

    @staticmethod
    def find_first_by(model_name, **kwargs):
        """
        根据提供的数据库表model name, 以及查询条件, 查询匹配到的第一条数据.
        :param model_name: 数据库表名称
        :param kwargs: 查询字段 where id = 1, name = abc
        :return: 一个 sqlalchemy model
        """
        item = None
        try:
            item = model_name.query.filter_by(**kwargs).first()
        except IntegrityError as e:
            current_app.logger.error("got IntegrityError db error please check")
            current_app.logger.error(e)
        except Exception as e:
            current_app.logger.error("got other db error please check")
            current_app.logger.error(e)
        finally:
            # print('*************************************')
            # print(type(items))
            # print(items)
            return item

    @staticmethod
    def create_item(model_name, **kwargs) -> bool:
        result = False
        try:
            new_to_db = model_name(**kwargs)
            db.session.add(new_to_db)
            db.session.commit()
            result = True
        except IntegrityError as e:
            current_app.logger.error("got IntegrityError db error please check")
            current_app.logger.error(e)
        except Exception as e:
            current_app.logger.error("got other db error please check")
            current_app.logger.error(e)
        finally:
            return result

    @staticmethod
    def update_item(model_name, item_mark: dict, update_value: dict) -> bool:
        """
        更新数据库item, 更新之前需要查询下数据存在不, 不存在直接返回更新失败.
        :param model_name: 要更新的数据库名称
        :param item_mark: 用于查找数据库数据的标志位
        :param update_value: 需要更新的数据
        :return:
        """
        result = False
        try:
            if model_name.query.filter_by(**item_mark).first() is None:
                current_app.logger.error(f"No items found by provided info: \t {item_mark}")
                return result
            model_name.query.filter_by(**item_mark).update(update_value)
            db.session.commit()
            result = True
        except IntegrityError as e:
            current_app.logger.error("got IntegrityError db error please check")
            current_app.logger.error(e)
        except Exception as e:
            current_app.logger.error("got other db error please check")
            current_app.logger.error(e)
        finally:
            return result

七. 一些简单的操作
  1. 多表查询, 排序, sql语句中and写法
# 多表查询指定数据时 
db.session.query(Model_A.id, Model_A.name, Model_B.value).filter(
	Model_A.id == Model_B.category_id, 
	and_(extract("year", Model_A.record_date) == '2022'),
	and_(Model_A.is_delete == 0)).order_by(Model_A.record_date.desc(),
	Model_A.create_time.desc()).all()

后续, 还涉及到多表联合查询, 这个还没有想明白. 要是有不正确的地方, 请指出, 谢谢.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值