掌握sqlalchemy关系:探索back_populates参数和不同的关系类型
#python #sql #orm #sqlalchemy

使用sqlalchemy设计关系数据库时,在表之间创建关系是很常见的。
这些关系定义了一个表中的数据与另一表中的数据如何相关。

这些关系的最重要参数之一是back-populates参数,该参数确定了SQLalchemy将如何自动填充相关数据。这是一个必不可少的功能,使ORM(对象关系映射)框架能够跟踪关系并确保保持数据一致性。
该参数用于指定两个表之间的关系,以及SQLalchemy将如何自动填充相关数据。从本质上讲,这是一个允许Sqlalchemy自动填充相关数据而无需手动指定每个查询中的关系的快捷方式。

Back-populates与sqlalchemy中的relationship()函数一起使用。它在关系的两边都定义,并允许自动群体的相关对象群体。这意味着,当一个对象更新时,其相关对象也会自动更新。

要了解back-populates参数,首先了解可以在sqlalchemy中创建的不同类型的关系很重要:

  • 一对一,
  • 一对多,
  • 多对一,
  • 多一到多。

一对一的关系

一对一的关系是Sqlalchemy中最简单的关系类型。当两个表与一个表中的每一行相关时,它们就会发生。

要使用back-populates来定义一对一的关系,您可以使用具有False值的uselist参数。这告诉sqlalchemy,这种关系是一种一对一的关系。

例如,Person表可能与License表有关,每个人都有一个许可证。关系可以定义如下:

from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class Person(Base):
    __tablename__ = 'person'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    license_id = Column(Integer, ForeignKey('license.id'))
    license = relationship('License', back_populates='person', uselist=False)

class License(Base):
    __tablename__ = 'license'
    id = Column(Integer, primary_key=True)
    car_brand = Column(String)
    plate_number = Column(String)
    person = relationship('Person', back_populates='license')

在上面的示例中,使用relationship()函数定义了PersonLicense之间的关系。 back_populates参数用于指定关系的License侧的反向关系。

一对一的关系

当一个表中的一排可能与另一个表中的许多行相关时,就会发生一对多的关系。为了使用back-populates定义一对多关系,您可以使用具有True值的uselist参数。
这告诉Sqlalchemy,这种关系是一对一的关系。

例如,考虑两个表-DepartmentEmployee
如果每个部门都有很多员工,则关系可以定义如下:

from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class Department(Base):
    __tablename__ = 'department'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    employees = relationship('Employee', back_populates='department', uselist=True)

class Employee(Base):
    __tablename__ = 'employee'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    department_id = Column(Integer, ForeignKey('department.id'))
    department = relationship('Department', back_populates='employees')

在上面的示例中,使用relationship()函数定义了DepartmentEmployee之间的关系。 back_populates参数用于指定关系的Employee侧的反向关系。

多一关系

当一个表中的许多行与另一个表中的一行相关时,就会发生多一关系。
要使用back-populates来定义多对一的关系,您可以使用具有False值的uselist参数。

例如,一个Comment表可能与Post表有关,其中多个注释可以与单个帖子关联。

from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class Post(Base):
    __tablename__ = 'posts'
    id = Column(Integer, primary_key=True)
    title = Column(String)
    comments = relationship('Comment', back_populates='post')

class Comment(Base):
    __tablename__ = 'comments'
    id = Column(Integer, primary_key=True)
    text = Column(String)
    post_id = Column(Integer, ForeignKey('posts.id'))
    post = relationship('Post', back_populates='comments', uselist=False),

在此示例中,我们有一个与Comment模型一对多关系的Post模型。评论关系是使用relationship()函数与back_populates参数集建立的,该参数设置为“ post”,这表明Post模型应具有相应的帖子属性,该属性映射到注释。

同样,Comment模型具有与back_populates设置为“注释”的帖子关系,以表明每个Comment对象只能具有一个相应的Post对象。设置了uselist=False参数以确保Comment对象的帖子属性是一个对象而不是列表。

多一的关系

当一个表中的多行与另一表中的多行相关时,就存在多到许多关系。 back-populates参数。
当与表之间的多对多关系工作时,此参数特别有用。

例如,Student表可能与Course表有关,每个学生都可以参加多个课程,并且每门课程都可以由多个学生参加。

在Sqlalchemy中使用多一对人际关系时,我们需要定义一个“中间”表,该表连接我们感兴趣的两个表。此中间表包含外国键,指向其他键两个表。我们可以使用sqlalchemy中的“关系”函数来定义这种关系,并指定“次级”参数以指示中间表的名称。
该中间表被称为关联表。

这是一个示例:

from sqlalchemy import Column, Integer, String, ForeignKey, Table
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

students_courses = Table('students_courses', Base.metadata,
    Column('student_id', Integer, ForeignKey('students.id')),
    Column('course_id', Integer, ForeignKey('courses.id'))
)

class Student(Base):
    __tablename__ = 'students'

    id = Column(Integer, primary_key=True)
    name = Column(String)
    courses = relationship('Course', secondary=students_courses, back_populates='students')

class Course(Base):
    __tablename__ = 'courses'

    id = Column(Integer, primary_key=True)
    name = Column(String)
    students = relationship('Student', secondary=students_courses, back_populates='courses')

在此示例中,我们有两个表“学生”和“课程”,由中间表连接,称为“ sustemass_courses”。 Student类使用“关系”函数定义了与Course类的关系,并将“辅助”参数设置为“ sustemass_courses”。 “ back_populate”参数也设置为“学生”,这表明每当添加学生或从课程中删除学生时,都应自动更新Course类的“学生”属性。

同样,Course类使用相同的relationship函数定义了与Student类的关系,并将secondary参数设置为“ Students_courses”,而back_populates参数设置为“ Courses”。

>

通过以这种方式使用back_populates参数,我们可以确保在两个表中对学生和课程之间的多一关系的变化进行了适当的反映。例如,如果我们将新课程添加到学生的课程列表中,则该课程将自动添加到该课程的学生列表中。而且,如果我们将学生从课程中删除,则该学生将自动从该课程的学生名单中删除。

总而言之,back_populates参数是SQLalchemy中的重要工具,用于定义和正确地表示表之间的关系。通过使用此参数来定义表之间的双向关系,我们可以确保在数据库的不同部分中正确同步和一致。