Flask框架(四)----ORM

本文介绍如何使用ORM模型类进行数据库操作,包括数据的增删改查,以及如何通过过滤器和执行器获取特定数据。同时,文章详细解释了如何通过角色模型和用户模型建立一对多的关系,以及如何利用外键实现数据关联。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

通过ORM模型类操作数据:重点

操作数据库(增删改查)

查:

模型类.query : 得到了该模型的所有结果集

模型类.query.过滤器: 得到的又是一个新的结果集

模型类.query.过滤器.执行器: 取出集里面的数据

注意点:

1.如果不指定数据的表名称,那么默认就是类名称的小写

2.如果需要指定,通过__tablename__ = '自定义表名'

增删改:

db.create_all(): 创建继承自db.Model的模型类

db.drop_all(): 删除数据库中所有的表(继承db.Model)

db.session.add(obj) 添加单个对象

db.session.add_all([obj1,obj2]) 增加多个

db.session.delete(obj) 删除当个对象

db.session.commit() 提交会话

db.session.rollback() 回滚

db.session.remove() 移除会话

from flask import Flask

from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)

#2. 设置数据库配置信息

app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://root:123456@127.0.0.1:3306/basic4"

app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False

# 3.创建对象

db = SQLAlchemy(app)

#角色模型(一方)

class Role(db.Model):

    __tablename__ = 'roles'

    #主键, 参数1:表示类型,  参数2: 约束范围

    id = db.Column(db.Integer,primary_key=True)

    name = db.Column(db.String(64),unique=True)

# 4.用户模型(多方)

class Person(db.Model):

    #主键, 参数1:表示类型,  参数2: 约束范围

    id = db.Column(db.Integer,primary_key=True)

name = db.Column(db.String(64),unique=True)

#外键

role_id = db.Column(db.Integer,db.ForeignKey(Role.id))

 #如果一个类继承自object,如果输出对象名称的时候显示的是地址值,如果想看到对象的内容可以重写__str__方法

    #如果继承自db.Model,需要重写: __repr__

    def __repr__(self):

        return "<User:%s,%s,%s,%s>"%(self.id,self.name,self.email,self.password)

@app.route('/')

def hello_world():

    return "helloworld"

if __name__ == '__main__':

    #为了演示方便,先删除因为会预解析运行两次所以先删除再创建

    db.drop_all()

    #db.create_all(): 创建继承自db.Model的模型类的表

    db.create_all()

#添加对象到数据

haha = Role(name=’admin’)

db.session.add(haha)

db.session.commit()

    p1 = Person(name='banzhang', role_id=haha.id)

db.session.add(p1)

db.session.add_all([p1,p2])

    db.session.commit()

    app.run(debug=True)

注意点:

1.如果不指定数据的表名称,那么默认就是类名称的小写

2.如果需要指定,通过__tablename__ = '自定义表名'

数据库增加,删除,修改操作:

增加:

user = User(name='laowang')

db.session.add(user)

db.session.commit()

修改:

user.name = 'xiaohua'

db.session.commit()

删除:

db.session.delete(user)

db.session.commit()

查询所有用户数据

User.query.all()

查询有多少个用户

User.query.count()

查询第1个用户

User.query.all()[0]

查询id为4的用户[3种方式]

User.query.get(4)

User.query.filter_by(id = 4).first()

User.query.filter(User.id == 4).first()

查询名字结尾字符为g的所有数据[开始/包含]

User.query.filter(User.name.endswith('g')).all()

User.query.filter(User.name.startswith('g')).all()

User.query.filter(User.name.contains('g')).all()

查询名字不等于wang的所有数据[2种方式]

User.query.filter(User.name!=’wang’).all()

from sqlalchemy import not_

User.query.filter(not_(User.name=’wang’))

查询名字和邮箱都以 li 开头的所有数据[2种方式]

User.query.filter(User.name.startswith('li'),User.email.startswith('li')).all()

User.query.filter(and_(User.name.startswith('li'),User.email.startswith('li'))).all()

查询password是 `123456` 或者 `email` 以 `itheima.com` 结尾的所有数据

User.query.filter(or_(User.password == '123456',User.email.endswith('itheima.com'))).all()

查询id为 [1, 3, 5, 7, 9] 的用户列表

User.query.filter(User.id.in_([1,3,5,7,9])).all()

查询name为liu的角色数据

user = User.query.filter(User.name == 'liu').first()

role = Role.query.filter(Role.id == user.role_id).first()

查询所有用户数据,并以邮箱排序

User.query.order_by(User.email).all()

User.query.order_by(User.email.desc()).all()

每页3个,查询第2页的数据

paginate = User.query.paginate(page, per_page,Error_out)

paginate = User.query.paginate(2,3,False)

page: 哪一个页

per_page: 每页多少条数据

Error_out: False 查不到不报错

pages: 共有多少页

items: 当前页数的所有对象

page: 当前页

Relationship,backref,lazy(项目常用)

问题1: 如果查询到角色数据之后,能不能快速查询到,哪些用户扮演了该角色

        role = Role.query.get(1)

        一般做法:

            users_list = User.query.filter(User.role_id == role.id).all()

        需要做到: 使用关系relationship,添加在一方

            users_list = role.users

需要在Role 中添加属性:

  users = db.relationship(User)

括号内填的是对应的类的名字,通过外键之间的关联直接使用查询到的当前的角色信息查找对应职位的员工,role.users。

问题2: 如果查询到用户数据之后,能不能快速查询到,该用户扮演了哪个角色

        user = User.query.get(1)

        一般做法:

        role = Role.query.get(user.role_id)   

        

        需要做到: 需要使用到反向关系属性backref

        role  = user.role

users = db.relationship(User,backref=role)

lazy: 懒加载,默认值是subquery,一旦查询到一个对象之后,会默认把其他关联的数据也查询出来,相当于默认执行上面的user.role,role.users,使用这些语句会返回对象,需要用all()方法返回。

      可以设置成dynamic,只有用到才去查

users = db.relationship(User,backref=role,lazy=dynamic)

多对多

#中间表,学生课程中间表

tb_student_course = db.Table(

    #表名

    "tb_student_course",

    #参数1:表示字段值,  参数2: 数据类型,  参数3: 外键 连接的表名的字段值

    db.Column("student_id",db.Integer,db.ForeignKey("students.id")),

    db.Column("course_id",db.Integer,db.ForeignKey("courses.id")))

#学生

class Student(db.Model):

    __tablename__ = "students"

    id = db.Column(db.Integer,primary_key=True)

    name = db.Column(db.String(64),unique=True,nullable=False)

    #关系属性 secondary设置多对多的连接表,多对多关系关系属性在哪个表设置都可以

    courses = db.relationship("Course",backref="students",secondary=tb_student_course)

    #为了查看方便

    def __repr__(self):

        return "<Student:%s>"%self.name

class Course(db.Model):

    __tablename__ = "courses"

    id = db.Column(db.Integer,primary_key=True)

    name = db.Column(db.String(64),unique=True,nullable=False)

    def __repr__(self):

        return "<Course:%s>"%self.name

数据库迁移

from flask_script import Manager

from flask_migrate import Migrate, MigrateCommand

2.使用Manager管理app

manager = Manager(app)

  1. 使用Migrate,关联app,db

Migrate = (app,db)

  1. 给manager,添加一个数据库操作命令

manager.add_command("db"(名称),MigrateCommand)

5.通过命令方式迁移 在中端执行

生成迁移脚本文件夹(一次就好)

python xxx.py db(是数据库操作命令的名称) init

将模型类,迁移成脚本(重复执行) 会在文件夹中生成一个版本

python xxx.py db migrate -m '注释'

将迁移脚本跟新到数据库(重复执行)

python xxx.py db upgrade / downgrade  [version]

查看当前版本

python demo02flask_migrate.py db current

    查看最新版本

python demo02flask_migrate.py db show

注意点:

1.迁移是备份的表结构,不是数据

2.降级有可能导致数据丢失

3.如果需要做数据备份,需要使用功能,比如: navicat, mysqlworkbench,等等工具

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值