FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [View Raw Code]   [Original HTTPS Page]

Notes/python-basic-notes/python-days/Day_34.md at master · We2one/Notes · GitHub

/ Notes Public

Latest commit

 

History

History
535 lines (406 loc) · 17.9 KB

File metadata and controls

535 lines (406 loc) · 17.9 KB

Flak 数据库与请求

1.Flask 数据库

1.1 ORM
  • ORM (Object Relational Mapping 对象映射关系) : 通过使用描述对象和数据库之间映射的元数据,将面向对象语言程序中的对象自动持久化到关系数据库中.
  • 本质 : 将数据从一种形式转换到另一种形式
1.2 Flask-SQLAlchemy 链接
  1. 安装 Flask-SQLAlchemy : pip install flask-sqlalchemy

  2. 使用

    1. 链接 SQLite 数据库 (python自带)

      1. 创建 dbSettings.py 文件 用于设置数据库

        import os
        
        class Config:
        	# 获取项目所在绝对路径
            # __file__ : 获取现在文件路径
        	BASE_DIR = os.path.abspath(os.path.dirname(__file__))
        	# 配置数据库的 URL
        	SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(BASE_DIR, "my_db.sqlite")
        	# 配置-查看映射的 sql 语句
        	# app.config['SQLALCHEMY_CEHO'] = True
        	# 动态追踪修改设置
        	SQLALCHEMY_TRACK_MODIFICATIONS = True
    2. 在 app.py 内引用 SQLite 设置

      from flask import Flask
      from flask_sqlalchemy import SQLAlchemy
      from db_setting import Config
      
      app = Flask(__name__)
      # 添加 app 的数据库设置
      app.config.from_object(Config)
      # 创建核心对象
      db = SQLAlchemy(app)
      
      class Student(db.Model):
      	id = db.Column(db.Integer, primary_key=True)
      	name = db.Column(db.String(32))
      
      # 同步表结构
      db.create_all()
      
      if __name__ == '__main__':
      	app.run()
  3. 链接 MySQL 数据库

    1. 安装 PyMySQL : pip install pymysql

    2. pymysql.install_as_MySQLdb() #2.x版本是内置的 MySQLdb 模块,3.x版本,MySQLdb 就不可以使用了

    3. 数据库创建需要存储数据的库 : CREATE DATABASE db_name charset=utf-8

    4. Flask-SQLAlchemy 链接数据库

      • 修改 SQLALCHEMY_DATABASE_URI 配置链接 MySQL 数据库

        • 链接内容 : SQLALCHEMY_DATABASE_URI = 'mysql://username:password@server/db_name'

          参数 说明
          mysql 协议名
          username 用户名
          password 密码

        | server | 主机IP | | db | 数据库名称 |

      • SQLALCHEMY_TRACK_MODIFICATIONS=True : 默认为 True ,追踪对象的修改并且发送信号

      1. 运行项目 : db.create_all()

        1. 执行 .create_all() 方法将被创建的模型同步生成表结构
        2. 注意 : .create_all()方法只能将新创建的模型同步表结构,如果模型修改或删除,.create_all()不会同步字段和属性
        from flask import Flask
        from flask import render_template
        from flask_sqlalchemy import SQLAlchemy
        import pymysql
        
        app = Flask(__name__)
        pymysql.install_as_MySQLdb()  # 2.x版本是内置的 MySQLdb 模块,3.x版本,MySQLdb 就不可以使用了
        # 链接数据库
        app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:root@127.0.0.1:3306/test'
        app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
        db = SQLAlchemy(app)
        class Student(db.Model):
        	__tablename__ = 'Student'
        	id = db.Column(db.Integer, primary_key=True, autoincrement=True)
        	name = db.Column(db.String(32))
        
        # 创建表
        db.create_all()
        # 删除表
        db.drop_all()
1.3 数据库建模
  • SQLALCHEMY 建模常用字段

    • 常用字段类型

      属性 描述
      Integer 整型
      Float 浮点型
      Date 时间类型(年月日)
      DateTime 时间类型(年月日时分秒)
      Text 长文本
      String 变长字符串
    • 常用字段属性

      属性 描述
      primary_key 主键
      unique 键值唯一性
      index 索引
      nullable 空值
      default 默认值
  • 建模需要描述的内容

    • 业务主体 : 网站中对象
    • 主体关系 : 对象之间联系
  • 员工表模型

    class Person(db.Model):
    	id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    	username = db.Column(db.String(32), unique=True)
    	password = db.Column(db.String(32))
    	nickname = db.Column(db.String(32), default="")
    	age = db.Column(db.Integer, default=18)
    	gender = db.Column(db.String(16), default="男")
    	score = db.Column(db.Float, nullable=True)
1.4 目录结构化
  1. app.py : 项目初始化,配置文件

    from flask import Flask
    from flask_sqlalchemy import SQLAlchemy
    from db_setting import Config
    
    app = Flask(__name__)
    app.config.from_object(Config)
    db = SQLAlchemy(app)
  2. main.py : 项目控制文件

    from __init__ import app
    
    if __name__ == '__main__':
    	app.run()
  3. models.py : 模型文件 (存放数据库模型)

    from __init__ import db
    
    class Student(db.Model):
    	id = db.Column(db.Integer, primary_key=True)
    	name = db.Column(db.String(32))
    
    # 同步表结构
    db.create_all()
  4. views.py : 视图文件 (存放引用视图)

    from __init__ import app
    from flask import render_template
    
    @app.route('/')
    def hello_world():
    	return 'Hello World!'
1.5 Flask-SQLAlchemy 操作
  1. 单表操作

    1. 增加数据

      1. 增加单条数据

        person = Person(
        	username = "小孙",
            password = "123456",
            nickname = "老孙",
            age = 12,
            score = 45.5
        )
      2. 增加多条数据

        person1 = Person(
        	username = "小孙",
            password = "123456",
            nickname = "老孙",
            age = 12,
            score = 45.5
        )
        person2 = Person(
        	username = "小张",
            password = "123456",
            nickname = "老张",
            age = 22,
            score = 45.5
        )
    2. 查询

      方法 说明 例子
      .query.all() 查询符合条件的所有内容,返回值为列表,没有值就返回空列表 查询当前所有员工
      person_list = Person.query.all()
      .query.get() 通过 id 进行查找,返回值为对象,没有值返回 None 查 id 为 255 的员工
      person_list = Person.query.get(255)
      .query.filter()


      .query.filter_by()
      过滤筛选 查所有年龄大于21的男生
      persion_list=Person.query.filter(Person.age>21,Person.gender=="男")
      查所有男生
      persion_list=Person.query.filter_by(gender=="男")
      like() 模糊查询
      % : 匹配0个或多个
      _ : 匹配一个
      查所有年龄大于21的吴姓男生
      persion_list=Person.query.filter(Person.age>21,Person.gender=="男",Person.nickname.like('吴%'))
      .query.filter().limit()
      .query.filter_by().limit()
      返回的数据条数 查10位年龄大于21的男生
      persion_list=Person.query.filter(Person.age>21,Person.gender=="男").limit(10)
      .query.filter().limit().offset()
      .query.filter_by().limit().offset()
      查询起始位置,以下标进行偏移 从第二十个开始,查10位年龄大于21的男生
      persion_list=Person.query.filter(Person.age>21,Person.gender=="男").limit(10).offset(20)
      .query.filter().limit().order_by()
      .query.filter_by().limit().order_by()
      排序
      顺序: .order_by(db_name.条件)
      逆序: .order_by(db_name.条件.desc())
      按照年龄排序,查询所有吴姓男同事,逆序
      persion_list=Person.query.filter(Person.gender=="男",Person.nickname.like('吴%')).order_by(Person.age.desc())
      max()、min()、count()、sum、avg 聚合查询 需要先引入 func 函数 from sqlalchemy import func
      查询所有物姓男生个数
      result = db.session.query(func.count(Person.id)).filter(Person.gender=="男",Person.nickname.like('吴%')).all()
      group_by(db_name.分组条件) 分组查询 需要先引入 func 函数 from sqlalchemy import func
      查询男女个数
      result = db.session.query(Person.gender, func.count(Persion.id)).group_by(Persion.gender).all()
      and_()、or_()、not_() 逻辑查询 需要先引入 函数 from sqlalchemy import and_,or_,not_
      查询所有吴姓同事或男同事
      person_list = Person.query.filter(or_(Person.gender=="男",Person.nickname.like("吴%")))
    3. 修改 : .session.commit()

      # 修改 id 为 5 的用户性别为男
      person = Person.query.get(5)
      person.gender = "男"
      db.session.commit()
    4. 删除

      # 删除 id 为 25 的用户
      person = Person.query.get(25)
      db.session.delete(person)
      db.session.commit()
  2. 封装

    1. 每一个模型都需要创建一个 id 字段,可以将冗余的代码封装成一个基类

    2. 所有数据都需要增加删改方案

      1. 增加

        def update(self):
            db.session.add()
            db.session.commit()
      2. 修改

    def update(self): db.session.commit()

       
       3. 删除
       
          ```python
    def update(self):
              db.session.delete()
        db.session.commit()
          ```
    
       4. 查询
    
    
1.6 Flask-SQLAlchemy 关系
  1. 一对多关系,采用外键 (foreign-key) 进行一对多约束

    1. 例如: 员工与职位关系

    2. 模型搭建

      ## 职位
      class Position(Base):
          __tablename__ = "position"
          p_name = db.Column(db.String(32))
          p_level = db.Column(db.Integer)
          p_person = db.relationship(
          	"Person" # 映射的类对象
              backref="our_position" # 反向映射,给person 表使用
          )
      ## 员工
      class Person(Base):
          # id = db.Column(db.Integer, primary_key=True, autoincrement=True)
          username = db.Column(db.String(32), unique=True)
          password = db.Column(db.String(32))
          nickname = db.Column(db.String(32), default="")
          age = db.Column(db.Integer, default=18)
          gender = db.Column(db.String(16), default=18)
          score = db.Column(db.Float, nullable=True)
          
          # 声明p_position 是一个外键整型字段,对应 position 表的 id
          p_position = db.Column(db.Integer, db.ForeignKey("position.id"))
      • __tablename__="" : 表格名
      • p_position = db.Column(db.Integer, db.ForeignKey("position.id")) : 声明p_position 是一个外键整型字段,对应 position 表的 id
      • p_person = db.relationship("Person", backref="our_position") : 创建字段反向映射多表,backref 多表中操作一表数据的字段
      • relationship : 单纯表象两个模型间关系,不体现在数据库的表结构中,只为实现一对多查询更加方便
      • 一对一关系 : 增加列表项 uselist=False
    3. 一对多操作增加

      1. 使用外键字段增加数据

        # 1. 增加职位,然后增加员工
        pos = Position(p_name="员工", p_level=1)
        pos.save()
        # 增加员工李四
        per = Person(username='李四', password="123456", nickname="小四", p_position=1)
        per.save()
        # 增加员工王五
        position = Position.query.filter_by(p_name="员工").first()
        per = Person(username='王五', password="123456", nickname="老五", p_position=position_id)
        per.save()
      2. 使用 relationship 正向操作 (relationship 所在模型到另一个模型) 增加数据

        # 2. 增加员工小王 为小组长
        per = Person()
        per.username = "小王"
        per.password="12212"
        per.nickname = "王组长"
        # 不需要给外键字段赋值
        per.save()
        # 此操作将会删除之前的关系,重新建立关系
        pos = Position.query.filter(Position.p_name="小组长").first()
        pos.p_person = [per]
        pos.save()
      3. 使用 relationship 反向操作 (另一个模型到relationship 所在模型) 增加数据

        # 3. 增加小二为主任
        per = Person()
        per.username = "小二"
        per.password="12212"
        per.nickname = "二主任"
        # 使用 backref 反向映射,值为职位对象
        # 此操作将会删除之前的关系,重新建立关系
        per.our_position = Position.query.filter_by(p_name="主任").first()
        per.save()
    4. 一对多查询

    查询 id = 1 的员工的职位

    反向操作

    person = Person.query.get(1) pos = person.our_position.p_name print(pos)

    查询员工职位的员工

    正向操作

    pos = Position.query.get(1) person_list = pos.p_person print(person_list)

  2. 多对多关系

    1. OA项目中的权限管理

      1. 主任 : 查看部门考勤、组织部门会议
      2. 经理 : 查看部门考勤、组织部门会议、招聘员工、开除员工
      3. 表一 : 描述职位 (职位名称、职位等级)
      4. 表二 : 描述权限 (权限名称)
      5. 多对多 : 同一职位可以有多个权限,一个权限可以给多个人
    2. 创建模型

      1. 中间表创建 (必须如此创建)

        # 创建中间表
        pos_per = db.Table(
        	'pos_per',  # 表名
        	db.Column('pos_id', db.Integer, db.ForeignKey("position_id")),
        	db.Column('per_id', db.Integer, db.ForeignKey('permission.id')),
        )
      2. 创建职位表 (反向映射员工表与权限表)

        # 创建职位表
        class Position(Base):
        	p_name = db.Column(db.String(32))
        	p_level = db.Column(db.Integer)
        	p_person = db.relationship(
        		"Person",
        		backref='our_position',
        	)
        	p_permission = db.relationship(
        		"Permission",
        		secondary=pos_per,
        		backref="p_position",
        	)
      3. 创建员工表 (外键连接职位表)

        # 创建员工表
        class Person(Base):
        	username = db.Column(db.String(32), unique=True)
        	password = db.Column(db.String(64))
        	nickname = db.Column(db.String(32))
        	age = db.Column(db.Integer)
        	gender = db.Column(db.String(16))
        	score = db.Column(db.Float)
        
        	p_position = db.Column(db.Integer, db.ForeignKey("position.id"))
      4. 创建权限表

        # 创建权限表
        class Permission(Base):
        	per_name = db.Column(db.String(256))
    3. 多对多操作增加数据

      1. 表中增加数据

        # 插入权限
        p_list = [
            "查看部门考勤",
            "组织部门会议",
            "招聘员工",
            "开除员工",
        ]
        for per in p_list:
            p = Permission()
            p.per_name = per
            p.save()
            # 插入职位
            pos1 = Position(p_name="主任", p_level=1)
            pos2 = Position(p_name="经理", p_level=2)
            pos1.save()
            pos2.save()
      2. 正向操作增加关系

        # 正向操作增加关系  Position -> Permission
        # 主任职位增加查看部门考勤权限
        pos = Position.query.filter(Position.p_name=="主任").first()
        per = Permission.query.filter(Permission.per_name=="查看部门考勤").first()
        pos.p_permission = [per]
        pos.save()
      3. 反向操作增加关系

        # 反向操作,招聘员工权限中增加经理的角色
        per = Permission.query.filter(Permission.per_name=="招聘员工").first()
        pos = Position.query.filter(Position.p_name=="经理").first()
        per.p_position = [pos]
        per.save()
    4. 多对多操作查询

      # 正向查询经理权限
      pos = Position.query.filter(Position.p_name=="经理").first()
      per = pos.p_permission
      print(per)
      # 反向查询拥有招聘员工的所有职位
      per = Permission.query.filter(Permission.per_name=="招聘员工").first()
      pos = per.p_position
      print(pos)

Back | FazBrowse Home | New Git URL