python—sqlalchemy简单使用方法,一对多,多对多,双向关系教程

发布时间 2023-09-22 14:38:35作者: 岳宗柯

数据库的连接


from flask import Flask
from flask_sqlalchemy import SQLAlchemy
 
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://postgres:123456@localhost:5432/postgres'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)

其中

postgres:数据库用户名

123456:数据库密码

localhost:为数据库的host

5432:为数据库的端口

postgres:数据库名称

表的创建

在 SQLAlchemy 中定义模型时,可以使用许多属性来规定表的字段的属性和行为,这些属性有很多,具体如下:

Column: 声明一个列。
String: 字符串类型,参数为指定字符串的最大长度,通常用于存储短文本、用户名等字符串类型的数据。
Text: 文本类型,用于存储大块文本。
Integer: 整数类型,通常用于存储数值类型的 ID 编号等。
Float: 浮点数类型,用于存储浮点类型的数据。
Boolean: 布尔类型,用于存储布尔类型的数据。
DateTime: 日期和时间类型,用于存储日期和时间信息。
Date: 日期类型,用于存储日期信息。
Time: 时间类型,用于存储时间信息。
ForeignKey: 外键类型,用于定义外键关系。
relationship: 定义 ORM 关系模型中的关系类型。
back_populates: 定义反向引用的属性名称。
primary_key=True: 指示该列是主键列。
unique=True: 指定该列的值必须是唯一的。
default: 指定该列的默认值。
nullable=False: 指定该列的值不能为空。
上述仅是一部分常用的属性,有些属性只针对某些类型的数据,具体使用时需要根据需要选择。

表的增删改查

# 创建数据库表
with app.app_context():
    db.create_all()
 
# 添加新用户到数据库
    user1 = User(username='alice', email='alice@example.com')
    user2 = User(username='bob', email='bob@example.com')
    db.session.add(user1)
    db.session.add(user2)
    db.session.commit()
 
# 查询所有用户
 
with app.app_context():
    # 查询所有用户
    users = User.query.all()
    for user in users:
        print(user.username, user.email)
 
    # 根据 id 查询用户
    user = User.query.get(1)
    print(user.username, user.email)
 
    # 根据 name 查询用户
    user = User.query.filter_by(name='Alicee').first()
    print(user.username, user.email)
    # 删除一条记录
    user = session.query(User).filter_by(id=1).first()
    session.delete(user)
 
    # 提交更改
    session.commit()
 
    # 删除所有记录
    session.query(User).delete()
 
    # 提交更改
    session.commit()
 
    # 更新一条记录
    user = session.query(User).filter_by(id=1).first()
    user.name = 'new name'
 
    # 提交更改
    session.commit()
 
    # 更新所有记录
    session.query(User).update({'name': 'new name'})
 
    # 提交更改
    session.commit()

总结一下:
增加操作:

session.add(obj): 向会话中添加一个对象。
session.bulk_save_objects(list): 批量向数据库中插入多条记录。
查询操作:

session.query(Model).filter(condition1, condition2, ...).all(): 查询满足给定条件的所有记录。
session.query(Model).filter(condition1, condition2, ...).first(): 查询满足给定条件的第一条记录。
session.query(Model).filter(condition1, condition2, ...).paginate(page, per_page): 分页查询满足给定条件的记录。
session.query(Model).group_by(column).all(): 根据指定列进行分组查询。
更新操作:

session.query(Model).filter(condition).update({column: value}): 更新满足给定条件的记录的某个列的值。
删除操作:

session.query(Model).filter(condition).delete(): 删除满足给定条件的所有记录。
session.query(Model).filter(condition).first().delete(): 删除满足给定条件的第一条记录。
这些指令可以组合运用,实现更加复杂的数据操作。在实际使用中,需要先根据需求选择恰当的查询条件,并在此基础上采用增、删、改等操作。同时,也要注意在操作完成后及时提交事务,以保证持久化到数据库中。

一对多的关系

首先我们创建父母与孩子的表

关系口诀:

多方:Foreignkey
一方:relationship

# 父母表为一
class Parent(db.Model):
    __tablename__ = "parent"
    id = Column(Integer, primary_key=True)
    name = Column(String(1024))
    childs = relationship("Child", backref="parent")
 
 
# 儿童表为多
class Child(db.Model):
    __tablename__ = "child"
    id = Column(Integer, primary_key=True)
    name = Column(String(1024))
    parent_id= Column(Integer, ForeignKey("parent.id"))
 
if __name__ == '__main__':
    with app.app_context():
        db.drop_all()
        db.create_all()

我们来添加父母与子女的例子

"""添加关系子女测试"""
with app.app_context():
    p1 = Parent(id=1, name="张爸爸")
    db.session.add(p1)
    db.session.commit()
 
with app.app_context():
    c1=Child(id=1,name="张三",parent_id=1)
    c2=Child(id=2,name="张四",parent_id=1)
    db.session.add(c1)
    db.session.add(c2)
    db.session.commit()

最后我们通过子女的关系打印出父母的名字

with app.app_context():
    childs=db.session.query(Child).filter(Child.parent_id==1).all()
    for child in childs:
        print(child.id,child.name,child.parent_id,child.parent.name)

结果为:

1 张三 1 张爸爸
2 张四 1 张爸爸

多对多的关系

我们建立一个学生与课程的表

一个学生对应多个课程

一个课程也有多个学生上课

我们需要引入第三张表作为中间表

# 中间表
class StudentToCourse(db.Model):
    __tablename__ = "student_to_course"
    id = db.Column(db.Integer,primary_key=True)
    student_id = db.Column(db.Integer, db.ForeignKey("student.id"))
    course_id = db.Column(db.Integer, db.ForeignKey("course.id"))
 
# 学生表
class Student(db.Model):
    __tablename__ = "student"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), nullable=False)
    courses = db.relationship("Course", secondary="student_to_course", backref="student")
 
# 课程表
class Course(db.Model):
    __tablename__ = "course"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), nullable=False)
    teacher = db.Column(db.String(64))

现在我们创建数据库的实例子

with app.app_context():
    s1=Student(id="1",name="张三")
    s2 = Student(id="2", name="李四")
    s3 = Student(id="3", name="王五")
    s=[s1,s2,s3]
    db.session.add_all(s)
    db.session.commit()
 
    c1=Course(id="1",name="python实训",teacher="张伟")
    c2=Course(id="2",name="sql实训",teacher="张一山")
    db.session.add(c1)
    db.session.add(c2)
    db.session.commit()
 
    t1=StudentToCourse(student_id=1,course_id=1)
    t2=StudentToCourse(student_id=1,course_id=2)
 
    t3=StudentToCourse(student_id=2,course_id=1)
    t4=StudentToCourse(student_id=2,course_id=2)
 
    t=[t1,t2,t3,t4]
    db.session.add_all(t)
    db.session.commit()

现在我们通过学生表来查询学生id为1的同学上的那几门课:

with app.app_context():
    student = db.session.query(Student).filter(Student.id == 1).first()
    print(student.id, student.name)
    for course in student.courses:
        print(course.id, course.name)

双向关系

建立一个学生表和班级表

一个学生在多个班级里面上课

一个班级里面有多个学生上课

我们建立一个双向关系,可以相互访问

class ClassStudent(db.Model):
    __tablename__ = 'class_student'
    class_id = Column(Integer, ForeignKey('class.id'), primary_key=True)
    student_id = Column(Integer, ForeignKey('student.id'), primary_key=True)
 
 
class Class(db.Model):
    __tablename__ = 'class'
    id = Column(Integer, primary_key=True)
    students = relationship("Student", secondary="class_student", back_populates="classes")
 
 
"""简而言之,backref和back_populates的区别就是,back_populates使用必须要两个表都要使用,当id指定了相应的用户,他们就相当于两个电脑通信了,可以共享对方的相应的属性。"""
"""来自博客:https://blog.csdn.net/sinat_41667855/article/details/118729091"""
 
 
class Student(db.Model):
    __tablename__ = 'student'
    id = Column(Integer, primary_key=True)
    classes = relationship("Class", secondary="class_student", back_populates="students")
 
 
if __name__ == '__main__':
    with app.app_context():
        db.drop_all()
        db.create_all()

让我们来建立实例

with app.app_context():
    s1 = Student(id=1)
    s2 = Student(id=2)
    s3 = Student(id=3)
    s4 = Student(id=4)
    s = [s1, s2, s3, s4]
    db.session.add_all(s)
    db.session.commit()
 
    c1 = Class(id=1)
    db.session.add(c1)
    db.session.commit()
 
    cs1 = ClassStudent(class_id=1, student_id=1)
    cs2 = ClassStudent(class_id=1, student_id=2)
    cs3 = ClassStudent(class_id=1, student_id=3)
    cs4 = ClassStudent(class_id=1, student_id=4)
 
    cs=[cs1,cs2,cs3,cs4]
    db.session.add_all(cs)
    db.session.commit()

让我们把内容打印出来

with app.app_context():
    # 通过学生访问该学生所在的班级
    student = db.session.query(Student).filter(Student.id == 1).first()
    print(student.id)
    for classes in student.classes:
        print(classes.id)
    
    # 通过班级访问所有在该班级的学生
    classs = db.session.query(Class).filter(Class.id == 1).first()
    print(classs.id)
 
    print("___________________________________________________________")
    for students in classs.students:
        print(students.id)