美文网首页
Flask-SQLAlchemy入门

Flask-SQLAlchemy入门

作者: 钉某人 | 来源:发表于2020-04-17 18:26 被阅读0次

    安装

    pip install flask-sqlalchemy
    

    windows如果出现安装错误:ERROR: Cannot unpack file xxxx,使用下面命令安装成功

    pip install -i https://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.tuna.tsinghua.edu.cn flask-sqlalchemy
    
    

    简单入门

    init.py:初始化的文件
    insertUserTable.py:创建所有的表,插入用户数据,查询用户数据

    # init.py
    from flask import Flask
    from flask_sqlalchemy import SQLAlchemy
    import sys
    import os
    
    app = Flask(__name__)
    
    # 创建数据库,并连接flask程序
    WIN = sys.platform.startswith('win')
    if WIN:
        prefix = 'sqlite:///'
    else:
        prefix = 'sqlite:////'
    dev_db = prefix + os.path.join(os.path.dirname(app.root_path), 'data.db')
    print("dev_db:", dev_db)
    app.config['SQLALCHEMY_DATABASE_URI'] = dev_db
    app.config['SECRET_KEY'] = 'secret string'
    # 设置每次请求结束后会自动提交数据库的改动
    app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
    # 查询时显示原始SQL语句
    app.config['SQLALCHEMY_ECHO'] = True
    db = SQLAlchemy(app)
    
    # 声明用户表
    class User(db.Model):
        id = db.Column(db.Integer, primary_key=True)
        username = db.Column(db.String(80), unique=True)
        email = db.Column(db.String(120), unique=True)
    
    
        def __init__(self, username, email):
            self.username = username
            self.email = email
    
    
        # 此方法是实例化对象的自我描述信息,相当于java的toString(),默认情况下返回:类名+object at 内存地址
        def __repr__(self):
            return '<User: %s %s >' % (self.username, self.email)
    
    
    
    
    # insertUserTable.py
    from demo.init import db, User
    '''
    创建用户数据并插入用户表,然后查询用户表中的数据
    '''
    db.drop_all()  # 删除所有的表
    db.create_all()  # 创建所有生命的表
    
    # 创建用户数据
    user1 = User('user1', 'user1@qq.com')
    user2 = User(username='user2', email='user2@qq.com')
    
    # 将创建好的用户数据插入到用户表中
    db.session.add(user1)
    db.session.add(user2)
    
    db.session.commit()
    
    # 查询用户表所有的用户数据
    users = User.query.all()
    print(users)
    

    执行输出如下:

    [<User: user1 user1@qq.com >, <User: user2 user2@qq.com >]
    

    常用的sqlalchemy字段类型

    类型名 python中的类型 说明
    Integer int 整数类型,32位
    SmallInteger int 取值范围小的整数,16位
    BigInteger int或long 不限制精度的整数
    Float float 浮点数
    Numeric decimal.Decimal 整数,32位
    String str 变长字符串
    Text str 变长字符串,对较长或不限制长度的字符串做了优化
    Unicode unicode 变长Unicode字符串
    UnicodeText unicode 变长Unicode字符串,对较长或不限长度的字符串做了优化
    Boolean bool 布尔值
    Date datetime.date 时间
    Time datetime.datetime 日期和时间
    LargeBinary str 二进制文件

    常用的列表项

    选项名 说明
    primary_key True表示表的主键
    unique True表示这列不允许出现重复的值
    index True表示为这列创建索引,提高查询效率
    nullable True表示允许有空值,False表示不允许有空值
    default 设置默认值

    常用的关系选项

    选项名 说明
    backref 在关系的另一模型中添加反向引用
    primary join 明确指定两个模型之间使用的联结条件
    uselist 如果为False,不使用列表,而使用标量值
    order_by 指定关系中记录的排序方式
    secondary 指定多对多关系中关系表的名字
    secondary join 在SQLALchemy中无法自行决定时,指定多对多关系中的二级联结条件

    flask-sqlalchemy配置项

    配置项的key 说明
    SQLALCHEMY_DATABASE_URI 用于连接数据库,例如:sqlite:////tmp/test.db(linux或mac),mysql://username:password@server/db
    SQLALCHEMY_BINDS 一个映射绑定 (bind) 键到 SQLAlchemy 连接 URIs 的字典。 更多的信息请参阅 绑定多个数据库。
    SQLALCHEMY_ECHO 设置成 True,显示原始SQL语句日志
    SQLALCHEMY_POOL_SIZE 数据库连接池的大小。默认是数据库引擎的默认值 (通常是 5)
    SQLALCHEMY_RECORD_QUERIES 可以用于显式地禁用或者启用查询记录。查询记录 在调试或者测试模式下自动启用。更多信息请参阅 get_debug_queries()
    SQLALCHEMY_NATIVE_UNICODE 可以用于显式地禁用支持原生的 unicode。这是 某些数据库适配器必须的(像在 Ubuntu 某些版本上的 PostgreSQL),当使用不合适的指定无编码的数据库 默认值时。
    SQLALCHEMY_POOL_RECYCLE 自动回收连接的秒数。这对 MySQL 是必须的,默认 情况下 MySQL 会自动移除闲置 8 小时或者以上的连接。 需要注意地是如果使用 MySQL 的话, Flask-SQLAlchemy 会自动地设置这个值为 2 小时
    SQLALCHEMY_MAX_OVERFLOW 控制在连接池达到最大值后可以创建的连接数。当这些额外的 连接回收到连接池后将会被断开和抛弃
    SQLALCHEMY_TRACK_MODIFICATIONS 如果设置成 True (默认情况),Flask-SQLAlchemy 将会追踪对象的修改并且发送信号。这需要额外的内存, 如果不必要的可以禁用它

    一对多关系

    假设有两张表:班级表Classe和学生表Student,Classe存储班级信息,Student存储学生信息;每个班级对应多个学生,
    一个学生只能对应一个班级,班级表Classe与学生表Students是一对多关系

    db.relationship()关系函数定义关系属性,
    这里让Classe指向Student类并加载多个,如果想要一对一关系,使用userlist=False,并设置给relationship()。

    backref是在一个Student类上声明新属性的简单方法,也可以通过stu._class来获取该学生所属班级
    lazy决定了SQLALCHEMY什么时候从数据库加载数据:

    • select : 默认属性。按需加载,即在访问到属性的时候,才会全部加载该属性的数据
    • joined : 加载记录,但使用联结
    • subquery : 与joined类似,立即加载,但使用子查询。
    • dynamic : 不加载记录,而是提供加载记录的查询,即生成一个query对象,方便进行条件过滤
    from demo.init import db
    
    class Student(db.Model):
        __tablename__ = 'students'
        id = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(64), nullable=False)
        # 定义外键(表明.字段名)
        class_id = db.Column(db.Integer, db.ForeignKey('classes.id'))
    
        def __repr__(self):
            return '<Student: %r>' % self.name
    
    class Classe(db.Model):
        __tablename__ = 'classes'
        id = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(64), nullable=False)
        # 使用关系函数定义关系属性
        students = db.relationship('Student', backref='_class', lazy='select')
    
        def __repr__(self):
            return '<Classe %r>' % self.name
    
    # 创建所有的表
    db.create_all()
    
    # 删除Student表和Classe表的所有行
    Student.query.delete()
    Classe.query.delete()
    
    # 创建数据,并插入数据库
    stu1 = Student(name='stu1')
    stu2 = Student(name='stu2')
    stu3 = Student(name='stu3')
    
    class1 = Classe(name='class1', students=[stu1])
    class2 = Classe(name='class2', students=[stu2, stu3])
    
    db.session.add_all([stu1, stu2, stu3, class1, class2])
    db.session.commit()
    
    # 查询所有学生
    stu_all = Student.query.all()
    print('全部学生:', stu_all)
    
    # 查询第一个学生所属班级
    stu_01 = stu_all[0]
    print("该学生所属班级:", stu_01._class)
    
    # 查询二班所有的学生
    stus_of_class2 = Student.query.filter_by(_class=class2).all()
    print('二班的学生:', stus_of_class2)
    
    # 查询全部班级
    cls_all = Classe.query.all()
    print('全部班级:', cls_all)
    
    # 查询二班所有的学生
    cls2 = Classe.query.filter_by(name='class2').first()
    print('二班学生:', cls2.students)
    

    多对多关系

    假设一堆学生学习不同的课程,这就是多对多关系
    多对多的关系中需要定义一个用于关系的辅助表,这个辅助表不使用模型,而是采用一个实际的表

    from demo.init import db
    
    '''
    多对多关系
    假设一堆学生学习不同的课程,这就是多对多关系
    '''
    tb_student_course = db.Table('tb_student_course',
                                 db.Column('student_id', db.Integer, db.ForeignKey('student.id')),
                                 db.Column('course_id', db.Integer, db.ForeignKey('courses.id')))
    
    class Student(db.Model):
        id = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(64), unique=True)
    
        # 关联属性,多对多的情况,可以写在任意一个模型类型中,含有正向引用和反向引用
        relate_courses = db.relationship('Course',
                                         secondary=tb_student_course,
                                         backref='relate_student',
                                         lazy='dynamic')
        def __repr__(self):
            return '<Student %r>' % self.name
    
    class Course(db.Model):
        __tablename__ = 'courses'
        id = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(64), unique=True)
    
        def __repr__(self):
            return '<Course %r>' % self.name
    
    # 创建所有表
    db.create_all()
    
    # 删除Student表和Course表的所有行
    Student.query.delete()
    Course.query.delete()
    
    # 添加数据
    stu1 = Student(name='张三')
    stu2 = Student(name='李四')
    stu3 = Student(name='王五')
    
    cou1 = Course(name='物理')
    cou2 = Course(name='化学')
    cou3 = Course(name='生物')
    
    # 添加关系
    stu1.relate_courses = [cou2, cou3]
    stu2.relate_courses = [cou2]
    stu3.relate_courses = [cou1, cou2, cou3]
    
    # 添加到数据库
    db.session.add_all([stu1, stu2, stu3, cou1, cou2, cou3])
    db.session.commit()
    
    # 查询张三学习的所有课程
    stu = Student.query.filter_by(name='张三').first()
    for course in stu.relate_courses:
        print('张三学习的课程:', course.name)
    
    # 查询学习生物这门课程的所有学生
    course = Course.query.filter_by(name='生物').first()
    for student in course.relate_student:
        print('学习生物的学生', student.name)
    

    操作数据库:增删改查

    from demo.init import db
    from sqlalchemy import and_
    '''
    操作数据库,增删改查
    '''
    
    class Kids(db.Model):
        id = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(255), nullable=False, unique=True)
        age = db.Column(db.Integer, nullable=False)
    
        def __repr__(self):
            return '<Kids name:%r age:%r>' % (self.name, self.age)
    
    # 查询所有的kid
    def queryAllKid():
        kids = Kids.query.all()
        print(kids)
    
    # 添加数据到数据库
    def add_data():
        kid1 = Kids(name='kid1', age=4)
        kid2 = Kids(name='kid2', age=5)
        kid3 = Kids(name='kid3', age=9)
        kid4 = Kids(name='kid4', age=12)
        kid5 = Kids(name='kid5', age=12)
        kid6 = Kids(name='kid6', age=12)
    
        db.session.add_all([kid1, kid2, kid3, kid4, kid5, kid6])
        db.session.commit()
    
    # 创建数据库表
    db.create_all()
    
    # 删除Kids表所有行
    Kids.query.delete()
    
    # ----------- 增 -------------
    # 添加一条数据
    kid1 = Kids(name='kid1', age=4)
    db.session.add(kid1)
    db.session.commit()
    
    # 添加多条数据(添加的是数组)
    kid2 = Kids(name='kid2', age=5)
    kid3 = Kids(name='kid3', age=9)
    kid4 = Kids(name='kid4', age=12)
    
    db.session.add_all([kid2, kid3, kid4])
    db.session.commit()
    
    queryAllKid()
    
    # ----------- 删 -------------
    
    # 先查询后删除
    kid_del_1 = Kids.query.filter_by(name='kid1').first()
    if kid_del_1 != None:
        db.session.delete(kid_del_1)
        db.session.commit()
    queryAllKid()
    
    # 删除Kids表所有行
    Kids.query.delete()
    queryAllKid()
    
    # ----------- 改 -------------
    add_data()
    # 修改,先查询后修改
    kid_update_1 = Kids.query.filter_by(name='kid1').first()
    if kid_update_1 != None:
        kid_update_1.name = 'kid_1_update'
        db.session.commit()
    queryAllKid()
    
    # ----------- 查 -------------
    
    # 原生slq语句查询,待补充
    sql = 'select * from kids'
    result_1 = db.session.execute(sql)
    
    # 查询全部
    result_2 = Kids.query.all()
    print('查询全部:', result_2)
    
    # 主键查询
    result_3 = Kids.query.get(1)
    print('主键查询:', result_3)
    
    # 单条件查询
    result_4 = Kids.query.filter_by(name='kid2').first()
    print('条件查询:', result_4)
    
    # 多条件查询
    result_5 = Kids.query.filter(and_(Kids.name == 'kid2', Kids.age == 5)).first()
    print('多条件查询:', result_5)
    
    # 比较查询 .__lt__(5):小于5,__le__(5):小于等于5,__gt__(5):大于5,__ge__(5):大于等于5
    result_6 = Kids.query.filter(Kids.age.__gt__(5)).all()
    print('比较查询:', result_6)
    
    # in查询
    result_7 = Kids.query.filter(Kids.name.in_(['kid1', 'kid2', 'kid3'])).all()
    print('in查询:', result_7)
    
    # 排序
    result_8 = Kids.query.order_by('age').all()
    print('排序:', result_8)
    
    # 限制查询,在符合age=12的结果中,跳过一个,剩下的结果选取前2个
    result_9 = Kids.query.filter_by(age=12).offset(1).limit(2).all() 
    print('限制查询:', result_9)
    
    

    源码地址

    相关文章

      网友评论

          本文标题:Flask-SQLAlchemy入门

          本文链接:https://www.haomeiwen.com/subject/uczyvhtx.html