python—sqlalchemy简单使用方法,一对多,多对多,双向关系教程
数据库的连接
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)