Flask数据库

一、Flask数据库

  • ORM

    对象关系映射(Object Relational Mapping,简称ORM)是通过使用描述对象和数据库之间映射的元数据,将面向对象语言程序中的对象自动持久化到关系数据库中

    一种设计思想,以面向对象形式操作数据库,将增删改查包装成了方法,不用sql语句(自动生成sql语句),可以根据实体类的映射创建表

  • Flask-sqlalchemy

    SQLAlchemy是Python开发的一个实现了ORM思想的模块,将Python面向对象的类映射为数据库的表,通过映射关系来完成数据库的操作,降低数据库操作的难度和繁琐程度

    Flask-SQLAlchemy 是一个为 Flask应用增加 SQLAlchemy支持的扩展。它致力于简化在 Flask中SQLAlchemy 的使用,提供了有用的默认值和额外的API来更简单地完成常见任务

    1. 安装flask-sqlalchemy

      pip install flask-sqlalchemy

    2. 简单使用

      链接sqlite数据库

      这是一个文件型数据库,用于微小型测试项目,正式项目使用mysql

      将生成是sqlalchemy文件拖到dabase面板中就可以打开了

注意:点击Test Connectction,下载 Driver Files

# 导入包
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import os
import pymysql
pymysql.install_as_MySQLdb()

# 创建flask的实例
app = Flask(__name__)

# 获取项目所在目录的绝对路径
BASE_DIR = os.path.abspath(os.path.dirname(__file__))

# 配置sqlite数据库的URI
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///" + os.path.join(BASE_DIR, "db.sqlite")

# 配置Mysql数据库的URL
# app.config["SQLALCHEMY_DATABASE_URI"] = "mysql://root:/oa"

# 配置动态追踪修改设置
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True

# 查看映射的sql语句
app.config["SQLALCHEMY_ECHO"] = True

# 创建sqlalchemy的核心对象
db = SQLAlchemy(app)


class Person(db.Model):
    id = db.Column(db.INT, primary_key=True, autoincrement=True)
    username = db.Column(db.VARCHAR(100))


# 同步数据库,如果表已经创建,忽略
db.create_all()
  1. 链接 Mysql 数据库

    链接mysql数据库

    (1) 需要安装依赖pymysql

    pip install pymysql

    (2) 数据库中创建一个数据库

    create database oa default charset=utf8;

    (3) 使用flask-sqlalchemy连接mysql数据库

    mysql://root:/oa

    mysql://用户名:密码@主机ip/数据库名

    (4) 运行项目

    执行create_all方法能将创建的模型类同步到表结构

    注意:create_all方法只能够将新创建的模型同步表结构,如果模型修改或者删除,create_all不会同步

    字段和属性

    __ tablename __:定义表的名称

    字段的类型

类型描述
Integer整型
Float浮点型整型
Date时间类型年月日
DateTime时间类型 年月日时分秒
Text长文本
String变长字符串

?

常见字段属性

属性描述
primary_key主键
unique键值唯一性
index索引
nullable空值
default默认值

三、数据库建模

  • 数据库学习难度不在基本语句,增删改查。对于开发来说,数据建模时相当有挑战性的,所谓的数据库建模:就是用数据库来描述业务逻辑,一个好的数据库模型代表整个网站成功一半,反之,如果数据库设计出了问题,项目多半不会成功

    • 建模需要描述的内容

      ? 业务主体:就是在这个网站当中的对象

      ? 主体关系:对象之间的联系

    • 比如 : OA系统

      ? 需要有员工数据表

      ? 需要有职位数据表

      ? 需要有部门数据表

      ? 首先使用字段来描述 员工,职位,部门

      ? 其次需要使用字段描述:

      ? 员工和职位是 多对一关系

      ? 部门和职位是 一对多关系

四、目录优化

当前所有的内容,包括视图、链接数据库及模型部分都在同一个文件中。这种单文件编程显示是不合理的,我们在学习如何链接数据库及模型中的常用属性后,要将模型放在项目中,首先优化我们的目录结构,将视图,配置信息,模型分别独立出来

  1. app.py项目初始化,配置文件

  2. modles.py模型文件

  3. viwes.py视图文件

  4. mian.py项目控制文件

五、flask-sqlalchemy操作

  1. 单表操作

    (1) 增加单条数据

    @app.route("/add/person")
    def add_person():
        """新增"""
        # 创建对象
        p = Person(
            username="小王",
            password="123456"
        )
        # 增加
        db.session.add(p)
        # 提交,增删改需要提交才会生效
        db.session.commit()
    
        return "add_person"

    (2) 增加多条数据

    @app.route("/add/person")
    def add_person():
        """新增"""
        # 创建对象
        p = Person(
            username="小王",
            password="123456"
        )
        p2 = Person(
            username="小赵",
            password="123456"
        )
        # 增加
        db.session.add_all([p,p2])
        # 提交,增删改需要提交才会生效
        db.session.commit()
    
        return "add_person"

    (3) 查询

    方法说明例子
    all查询符合条件的所有内容,返回值为列表,没有值返回空列表查询当前所有员工person_list = Person.query.all()
    get通过id进行查找,返回值为对象,没有值返回None查id为288的员工person= Person.query.get(288)
    filter过滤筛选##查所有男生 person_list = Person.query.filter_by(gender = "男")
    filter_by过滤筛选#查所有年龄大于21岁的男同事 person_list = Person.query.filter(Person.age > 21,Person.gender=="男")
    like模糊查询% 匹配0个或者多个_ 匹配一个# 查所有年龄大于21岁的吴姓男同事 person_list = Person.query.filter( Person.age > 21, Person.gender=="男", Person.nickname.like("吴%") )
    limit返回的数据的条数# 查10位年龄大于21岁的男同事 person_list = Person.query.filter( Person.age > 21, Person.gender=="男" ).limit(10)
    offset查询起始位置,以下标进行偏移# 从第二十个开始,查询10位年龄大于21岁的男同事 person_list = Person.query.filter( Person.age > 21, Person.gender=="男" ).limit(10).offset(20)
    order_by排序# 按照年龄排序,查询所有吴姓男同事,正序 person_list = Person.query.filter( Person.gender=="男", Person.nickname.like("吴%") ).order_by(Person.age)
    max min count sum avg聚合查询#查询所有吴姓男生的个数from sqlalchemy import func result = db.session.query(func.count(Person.id) ).filter(Person.gender == "男",Person.nickname.like("吴%")).all()
    group_by分组#分组查询 from sqlalchemy import func #查询男女个数 result = db.session.query( Person.gender, func.count(Person.id) ).group_by(Person.gender).all() #查询年龄个数 result = db.session.query( Person.age, func.count(Person.id) ).group_by(Person.age).all() print(result)
    and_or_not_逻辑查询 导入from sqlalchemy import and_,or_,not_# 查询所有吴姓男生 person_list = Person.query.filter( Person.gender"男", Person.nickname.like("吴%") ) #查询所有吴姓同事或者男同事 person_list = Person.query.filter( or_( Person.gender"男", Person.nickname.like("吴%") ) )

    (4)修改

    @app.route("/update")
    def update():
        """修改"""
        # 查询
        person = Person.query.get(1)
        if person:
            # 修改
            person.password = 33
        # 提交,增删改需要提交才会生效
        db.session.commit()
    
        return "update"

    (5) 删除

    @app.route("/delete")
    def delete():
        """修改"""
        # 查询
        person = Person.query.get(1)
        if person:
            # 删除
            db.session.delete(person)
        # 提交,增删改需要提交才会生效
        db.session.commit()
    
        return "delete"
  • 封装

    (1) 每个模型都要创建一个id字段,基于面向对象的思想,将冗余的代码封装到一个父类

    (2) 所有的模型都需要增删改方法

    class Base(db.Model):
        """基类"""
        # 作为父类被继承,不会被创建成表(抽象)
        __abstract__ = True
        id = db.Column(db.Integer, primary_key=True, autoincrement=True)  # id
    
        def save(self):
            db.session.add(self)
            db.session.commit()
    
        def delete(self):
            db.session.delete(self)
            db.session.commit()
    
        def update(self):
            db.session.commit()

六、flask-sqlalchemy 关系

我们已经了解如何进行数据库的搭建和基本的增删改查,但是在数据库建模的过程当中,不止有基于业务主体描述数据库模型,还有关系模型,常用的关系有以下两种

1、一对多关系

例如:职位和员工是一对多关系,一个员工可以有一个职位,一个职位可以对应多个员工

在数据库当中,通常采用外键来进行一对多约束。使用foreign-key就可以达成外键

(1)模型搭建

在多表当中创建一个字段,定义为int类型,用来存储一表的id,一表表名小写

position_id = db.Column(db.Integer,db.ForeignKey("position.id"))

在一表当中,创建字段反向映射向多表。backref是在多表当中操作一表数据的字段。

persons = db.relationship("Person", backref="position")

relationship:只是单纯的表现了两个模型类之间的关系,并不会体现在数据库的表结构中,只是为了在进行一对多的查询中更加的方便使用。在本例中:persons 用来一表反查多表、Person多表类名、backref 是多表查询一表的对应数据的字段

注:一对一关系只需要增加列表项: uselist=Flase 即可

2、多对多关系

在OA项目中,还有权限管理

首先主任有查看部门考勤和组织部门会议的权限

经理具有查看部门考勤,组织部门会议,招聘员工,开除员工的权限

表一:描述职位,例如:职位名称,职位等级

表二:描述权限,例如:权限名称

表一和表二是多对多的关系,一个职位可以有多种权限,一种权限可以给多个职位

相关推荐