自动映射

定义 sqlalchemy.ext.declarative 系统的扩展,该系统自动从数据库模式生成映射类和关系,通常从反射的模式生成,但并非必须如此。

希望 AutomapBase 系统可以为非常著名的 SQLSoup 所尝试解决的问题提供一个快速且现代化的解决方案,即从现有的数据库动态生成快速且基本的 ​​对象模型。通过严格地在映射器配置级别解决问题,并与现有的声明式类技术完全集成,AutomapBase 旨在为快速自动生成临时映射的问题提供一种良好集成的解决方案。

提示

自动映射 扩展面向“零声明”方法,其中完整的 ORM 模型(包括类和预先命名的关系)可以从数据库模式动态生成。对于仍希望使用显式类声明(包括显式关系定义)以及与表反射结合使用的应用程序,DeferredReflection 类(在 使用 DeferredReflection 中描述)是更好的选择。

基本用法

最简单的用法是将现有数据库反映到新模型中。我们以类似于创建声明式基类的方式创建一个新的 AutomapBase 类,使用 automap_base()。然后,我们调用 AutomapBase.prepare() 方法,要求它反映模式并生成映射

from sqlalchemy.ext.automap import automap_base
from sqlalchemy.orm import Session
from sqlalchemy import create_engine

Base = automap_base()

# engine, suppose it has two tables 'user' and 'address' set up
engine = create_engine("sqlite:///mydatabase.db")

# reflect the tables
Base.prepare(autoload_with=engine)

# mapped classes are now created with names by default
# matching that of the table name.
User = Base.classes.user
Address = Base.classes.address

session = Session(engine)

# rudimentary relationships are produced
session.add(Address(email_address="[email protected]", user=User(name="foo")))
session.commit()

# collection-based relationships are by default named
# "<classname>_collection"
u1 = session.query(User).first()
print(u1.address_collection)

在上面,调用 AutomapBase.prepare() 方法并传递 AutomapBase.prepare.reflect 参数表示 MetaData.reflect() 方法将被调用到这个声明式基类的 MetaData 集合中;然后,MetaData 中的每个可用 Table 将自动生成一个新的映射类。连接各个表的 ForeignKeyConstraint 对象将用于在类之间生成新的双向 relationship() 对象。类和关系遵循我们可以自定义的默认命名方案。此时,我们的基本映射(由相关的 UserAddress 类组成)已准备好以传统方式使用。

注意

可用意味着为了映射一个表,它必须指定一个主键。此外,如果检测到该表是两个其他表之间的纯关联表,则它将不会被直接映射,而是被配置为这两个引用表映射之间的多对多表。

从现有元数据生成映射

我们可以将预先声明的 MetaData 对象传递给 automap_base()。此对象可以以任何方式构造,包括以编程方式、从序列化文件或通过使用 MetaData.reflect() 方法进行反射。下面,我们演示了反射和显式表声明的组合

from sqlalchemy import create_engine, MetaData, Table, Column, ForeignKey
from sqlalchemy.ext.automap import automap_base

engine = create_engine("sqlite:///mydatabase.db")

# produce our own MetaData object
metadata = MetaData()

# we can reflect it ourselves from a database, using options
# such as 'only' to limit what tables we look at...
metadata.reflect(engine, only=["user", "address"])

# ... or just define our own Table objects with it (or combine both)
Table(
    "user_order",
    metadata,
    Column("id", Integer, primary_key=True),
    Column("user_id", ForeignKey("user.id")),
)

# we can then produce a set of mappings from this MetaData.
Base = automap_base(metadata=metadata)

# calling prepare() just sets up mapped classes and relationships.
Base.prepare()

# mapped classes are ready
User = Base.classes.user
Address = Base.classes.address
Order = Base.classes.user_order

从多个模式生成映射

AutomapBase.prepare() 方法在与反射一起使用时,最多只能一次从一个模式中反射表,使用 AutomapBase.prepare.schema 参数来指示要从中反射的模式名称。为了使用来自多个模式的表来填充 AutomapBase,可以多次调用 AutomapBase.prepare() 方法,每次调用时都将不同的名称传递给 AutomapBase.prepare.schema 参数。 AutomapBase.prepare() 方法会维护一个已映射 Table 对象的内部列表,并且只为自上次运行 AutomapBase.prepare() 以来新增的 Table 对象添加新的映射

e = create_engine("postgresql://scott:tiger@localhost/test")

Base.metadata.create_all(e)

Base = automap_base()

Base.prepare(e)
Base.prepare(e, schema="test_schema")
Base.prepare(e, schema="test_schema_2")

版本 2.0 中的新内容: AutomapBase.prepare() 方法可以被调用任意次数;每次运行时,只为新添加的表进行映射。在 1.4 及更早版本中,多次调用会导致错误,因为它会尝试重新映射已映射的类。以前使用 MetaData.reflect() 直接调用的解决方法仍然可以使用。

跨多个模式自动映射同名表

对于多个模式可能具有相同名称的表,因此将生成相同名称的类的情况,可以通过使用 AutomapBase.prepare.classname_for_table 钩子以基于每个模式应用不同的类名,或者使用 AutomapBase.prepare.modulename_for_table 钩子来解决冲突,该钩子允许通过更改其有效的 __module__ 属性来消除相同名称的类的歧义。在下面的示例中,此钩子用于为所有类创建 __module__ 属性,其格式为 mymodule.<schemaname>,其中,如果不存在模式,则使用模式名称 default

e = create_engine("postgresql://scott:tiger@localhost/test")

Base.metadata.create_all(e)


def module_name_for_table(cls, tablename, table):
    if table.schema is not None:
        return f"mymodule.{table.schema}"
    else:
        return f"mymodule.default"


Base = automap_base()

Base.prepare(e, modulename_for_table=module_name_for_table)
Base.prepare(e, schema="test_schema", modulename_for_table=module_name_for_table)
Base.prepare(e, schema="test_schema_2", modulename_for_table=module_name_for_table)

相同名称的类被组织成一个层次结构集合,可从 AutomapBase.by_module 获取。使用特定包/模块的点分隔名称遍历此集合,直到到达所需的类名。

注意

当使用 AutomapBase.prepare.modulename_for_table 钩子返回一个新的 __module__(它不是 None)时,该类**不会**被放置到 AutomapBase.classes 集合中;只有没有显式模块名的类会被放置在这里,因为该集合不能单独表示相同名称的类。

在上面的示例中,如果数据库在所有三个默认模式、test_schema 模式和 test_schema_2 模式中包含名为 accounts 的表,那么三个独立的类将可用为

Base.by_module.mymodule.default.accounts
Base.by_module.mymodule.test_schema.accounts
Base.by_module.mymodule.test_schema_2.accounts

为所有 AutomapBase 类生成的默认模块命名空间是 sqlalchemy.ext.automap。如果没有使用 AutomapBase.prepare.modulename_for_table 钩子,则 AutomapBase.by_module 的内容将完全在 sqlalchemy.ext.automap 命名空间内(例如 MyBase.by_module.sqlalchemy.ext.automap.<classname>),它将包含与在 AutomapBase.classes 中看到的一系列相同的类。因此,通常只需要在存在显式 __module__ 约定时才使用 AutomapBase.by_module

显式指定类

提示

如果希望在应用程序中突出显示显式类,请考虑使用 DeferredReflection

automap 扩展允许以类似于 DeferredReflection 类的方式显式定义类。从 AutomapBase 扩展的类就像常规的声明性类,但它们在构造后不会立即被映射,而是在我们调用 AutomapBase.prepare() 时被映射。 AutomapBase.prepare() 方法将根据我们使用的表名使用我们已建立的类。如果我们的模式包含表 useraddress,我们可以定义一个或两个类来使用

from sqlalchemy.ext.automap import automap_base
from sqlalchemy import create_engine

# automap base
Base = automap_base()


# pre-declare User for the 'user' table
class User(Base):
    __tablename__ = "user"

    # override schema elements like Columns
    user_name = Column("name", String)

    # override relationships too, if desired.
    # we must use the same name that automap would use for the
    # relationship, and also must refer to the class name that automap will
    # generate for "address"
    address_collection = relationship("address", collection_class=set)


# reflect
engine = create_engine("sqlite:///mydatabase.db")
Base.prepare(autoload_with=engine)

# we still have Address generated from the tablename "address",
# but User is the same as Base.classes.User now

Address = Base.classes.address

u1 = session.query(User).first()
print(u1.address_collection)

# the backref is still there:
a1 = session.query(Address).first()
print(a1.user)

上面,一个更复杂的细节是,我们说明了覆盖 relationship() 对象之一,而 automap 会创建这些对象。要做到这一点,我们需要确保名称与 automap 通常生成的名称匹配,因为关系名将是 User.address_collection,并且从 automap 的角度来看,引用的类的名称称为 address,即使我们在使用此类时将其称为 Address

覆盖命名方案

automap 的任务是基于模式生成映射的类和关系名,这意味着它在确定这些名称的方式方面有决策点。这三个决策点是使用可以传递给 AutomapBase.prepare() 方法的函数提供的,被称为 classname_for_table()name_for_scalar_relationship()name_for_collection_relationship()。任何或所有这些函数都像下面的示例一样提供,其中我们使用“驼峰式”方案来命名类,并使用 Inflect 包来命名集合的“复数形式”

import re
import inflect


def camelize_classname(base, tablename, table):
    "Produce a 'camelized' class name, e.g."
    "'words_and_underscores' -> 'WordsAndUnderscores'"

    return str(
        tablename[0].upper()
        + re.sub(
            r"_([a-z])",
            lambda m: m.group(1).upper(),
            tablename[1:],
        )
    )


_pluralizer = inflect.engine()


def pluralize_collection(base, local_cls, referred_cls, constraint):
    "Produce an 'uncamelized', 'pluralized' class name, e.g."
    "'SomeTerm' -> 'some_terms'"

    referred_name = referred_cls.__name__
    uncamelized = re.sub(
        r"[A-Z]",
        lambda m: "_%s" % m.group(0).lower(),
        referred_name,
    )[1:]
    pluralized = _pluralizer.plural(uncamelized)
    return pluralized


from sqlalchemy.ext.automap import automap_base

Base = automap_base()

engine = create_engine("sqlite:///mydatabase.db")

Base.prepare(
    autoload_with=engine,
    classname_for_table=camelize_classname,
    name_for_collection_relationship=pluralize_collection,
)

从上面的映射中,我们现在将有类 UserAddress,其中,从 UserAddress 的集合被称为 User.addresses

User, Address = Base.classes.User, Base.classes.Address

u1 = User(addresses=[Address(email="[email protected]")])

关系检测

automap 完成的大部分工作是基于外键生成 relationship() 结构。以下是此机制针对多对一和一对多关系的工作原理

  1. 一个给定的 Table(已知映射到特定类)将被检查是否有 ForeignKeyConstraint 对象。

  2. 对于每个 ForeignKeyConstraint,存在的远程 Table 对象将与要映射到它的类(如果有)匹配,否则将被跳过。

  3. 由于我们正在检查的 ForeignKeyConstraint 对应于从立即映射的类到该类的引用,因此关系将被设置为多对一,引用该类;一个对应的多对一反向引用将被创建到该类上,引用该类。

  4. 如果 ForeignKeyConstraint 中的任何列不可为空(例如 nullable=False),则 relationship.cascade 关键字参数将被设置为 all, delete-orphan,并将被添加到要传递给关系或反向引用的关键字参数中。如果 ForeignKeyConstraint 报告 ForeignKeyConstraint.ondelete 被设置为 CASCADE(对于非空值)或 SET NULL(对于可为空的列集),则选项 relationship.passive_deletes 标志被设置为 True,作为关系关键字参数集的一部分。请注意,并非所有后端都支持反射 ON DELETE。

  5. 关系的名称是使用 AutomapBase.prepare.name_for_scalar_relationshipAutomapBase.prepare.name_for_collection_relationship 可调用函数来确定的。需要注意的是,默认的关系命名是从**实际的类名**派生名称的。如果您为特定类声明了显式名称,或者指定了其他类命名方案,那么将从该名称派生关系名称。

  6. 会检查这些类是否具有匹配这些名称的现有映射属性。如果在一侧检测到一个,但在另一侧没有检测到,则 AutomapBase 会尝试在缺失的一侧创建一个关系,然后使用 relationship.back_populates 参数将新的关系指向另一侧。

  7. 在通常情况下,如果两侧都没有关系,则 AutomapBase.prepare() 会在“多对一”侧生成一个 relationship(),并使用 relationship.backref 参数将其与另一侧匹配。

  8. relationship()(以及可选的 backref())的生成将交给 AutomapBase.prepare.generate_relationship 函数,该函数可以由最终用户提供,以增强传递给 relationship()backref() 的参数,或者使用这些函数的自定义实现。

自定义关系参数

AutomapBase.prepare.generate_relationship 钩子可用于向关系添加参数。在大多数情况下,我们可以使用现有的 generate_relationship() 函数来返回对象,在将我们自己的参数添加到给定的关键字字典后。

以下是将 relationship.cascaderelationship.passive_deletes 选项发送到所有一对多关系的说明。

from sqlalchemy.ext.automap import generate_relationship
from sqlalchemy.orm import interfaces


def _gen_relationship(
    base, direction, return_fn, attrname, local_cls, referred_cls, **kw
):
    if direction is interfaces.ONETOMANY:
        kw["cascade"] = "all, delete-orphan"
        kw["passive_deletes"] = True
    # make use of the built-in function to actually return
    # the result.
    return generate_relationship(
        base, direction, return_fn, attrname, local_cls, referred_cls, **kw
    )


from sqlalchemy.ext.automap import automap_base
from sqlalchemy import create_engine

# automap base
Base = automap_base()

engine = create_engine("sqlite:///mydatabase.db")
Base.prepare(autoload_with=engine, generate_relationship=_gen_relationship)

多对多关系

automap 会生成多对多关系,例如那些包含 secondary 参数的关系。生成这些关系的过程如下

  1. 在分配任何映射类之前,会检查给定的 Table 是否包含 ForeignKeyConstraint 对象。

  2. 如果该表包含两个且仅包含两个 ForeignKeyConstraint 对象,并且该表中的所有列都是这两个 ForeignKeyConstraint 对象的成员,则该表被假定为“辅助”表,并且**不会直接映射**。

  3. Table 所引用的两个(或一个,对于自引用)外部表将与将被映射到它们的类匹配(如果有)。

  4. 如果找到了两侧的映射类,则会在这两个类之间创建一个双向多对多 relationship() / backref() 对。

  5. 多对多的覆盖逻辑与一对多/多对一的覆盖逻辑相同;将调用 generate_relationship() 函数来生成结构,并将维护现有属性。

具有继承的关系

automap 不会生成任何在继承关系中的两个类之间的关系。也就是说,给定以下两个类

class Employee(Base):
    __tablename__ = "employee"
    id = Column(Integer, primary_key=True)
    type = Column(String(50))
    __mapper_args__ = {
        "polymorphic_identity": "employee",
        "polymorphic_on": type,
    }


class Engineer(Employee):
    __tablename__ = "engineer"
    id = Column(Integer, ForeignKey("employee.id"), primary_key=True)
    __mapper_args__ = {
        "polymorphic_identity": "engineer",
    }

来自 EngineerEmployee 的外键不用于关系,而是用于建立这两个类之间的连接继承。

请注意,这意味着 automap 不会为从子类到超类的外键生成任何关系。如果映射具有从子类到超类的实际关系,那么这些关系需要明确指定。在下文中,由于我们从 EngineerEmployee 有两个单独的外键,因此我们需要同时设置我们想要的关系以及 inherit_condition,因为这些不是 SQLAlchemy 可以猜测的内容。

class Employee(Base):
    __tablename__ = "employee"
    id = Column(Integer, primary_key=True)
    type = Column(String(50))

    __mapper_args__ = {
        "polymorphic_identity": "employee",
        "polymorphic_on": type,
    }


class Engineer(Employee):
    __tablename__ = "engineer"
    id = Column(Integer, ForeignKey("employee.id"), primary_key=True)
    favorite_employee_id = Column(Integer, ForeignKey("employee.id"))

    favorite_employee = relationship(Employee, foreign_keys=favorite_employee_id)

    __mapper_args__ = {
        "polymorphic_identity": "engineer",
        "inherit_condition": id == Employee.id,
    }

处理简单的命名冲突

在映射期间发生命名冲突的情况下,请根据需要覆盖 classname_for_table()name_for_scalar_relationship()name_for_collection_relationship()。例如,如果 automap 尝试将多对一关系命名为与现有列相同的名称,则可以选择其他约定。给定一个模式

CREATE TABLE table_a (
    id INTEGER PRIMARY KEY
);

CREATE TABLE table_b (
    id INTEGER PRIMARY KEY,
    table_a INTEGER,
    FOREIGN KEY(table_a) REFERENCES table_a(id)
);

上面的模式将首先将 table_a 表自动映射为名为 table_a 的类;然后,它将在该类上自动映射一个指向 table_b 的关系,其名称与该相关类相同,例如 table_a。此关系名称与映射列 table_b.table_a 冲突,并且会在映射时发出错误。

我们可以通过使用下划线来解决此冲突,如下所示

def name_for_scalar_relationship(base, local_cls, referred_cls, constraint):
    name = referred_cls.__name__.lower()
    local_table = local_cls.__table__
    if name in local_table.columns:
        newname = name + "_"
        warnings.warn("Already detected name %s present.  using %s" % (name, newname))
        return newname
    return name


Base.prepare(
    autoload_with=engine,
    name_for_scalar_relationship=name_for_scalar_relationship,
)

或者,我们可以在列端更改名称。可以使用在 显式命名声明性映射列 中描述的技术来修改映射的列,方法是将列显式分配给新名称

Base = automap_base()


class TableB(Base):
    __tablename__ = "table_b"
    _table_a = Column("table_a", ForeignKey("table_a.id"))


Base.prepare(autoload_with=engine)

将 Automap 与显式声明一起使用

如前所述,automap 不依赖于反射,并且可以使用 Table 对象的任何集合,这些对象位于 MetaData 集合中。由此可以得出,automap 也可以用于生成缺失的关系,前提是给定一个完整定义了表元数据的完整模型。

from sqlalchemy.ext.automap import automap_base
from sqlalchemy import Column, Integer, String, ForeignKey

Base = automap_base()


class User(Base):
    __tablename__ = "user"

    id = Column(Integer, primary_key=True)
    name = Column(String)


class Address(Base):
    __tablename__ = "address"

    id = Column(Integer, primary_key=True)
    email = Column(String)
    user_id = Column(ForeignKey("user.id"))


# produce relationships
Base.prepare()

# mapping is complete, with "address_collection" and
# "user" relationships
a1 = Address(email="u1")
a2 = Address(email="u2")
u1 = User(address_collection=[a1, a2])
assert a1.user is u1

在上面,给定基本完整的 UserAddress 映射,我们在 Address.user_id 上定义的 ForeignKey 允许在映射的类上生成双向关系对 Address.userUser.address_collection

请注意,当子类化 AutomapBase 时,需要 AutomapBase.prepare() 方法;如果没有调用该方法,那么我们声明的类将处于未映射状态。

拦截列定义

MetaDataTable 对象支持一个事件钩子 DDLEvents.column_reflect(),它可用于在构建 Column 对象之前拦截关于数据库列的反映信息。例如,如果我们想使用 "attr_<columnname>" 这样的命名约定来映射列,则可以应用该事件,如下所示

@event.listens_for(Base.metadata, "column_reflect")
def column_reflect(inspector, table, column_info):
    # set column.key = "attr_<lower_case_name>"
    column_info["key"] = "attr_%s" % column_info["name"].lower()


# run reflection
Base.prepare(autoload_with=engine)

版本 1.4.0b2 新版功能: DDLEvents.column_reflect() 事件可以应用于 MetaData 对象。

API 参考

对象名称 描述

automap_base([declarative_base], **kw)

生成一个声明性自动映射基类。

AutomapBase

“自动映射”架构的基类。

classname_for_table(base, tablename, table)

返回应使用的类名,给出表的名称。

generate_relationship(base, direction, return_fn, attrname, ..., **kw)

为两个映射类生成 relationship()backref()

name_for_collection_relationship(base, local_cls, referred_cls, constraint)

返回用于从一个类引用另一个类的属性名,用于集合引用。

name_for_scalar_relationship(base, local_cls, referred_cls, constraint)

返回用于从一个类引用另一个类的属性名,用于标量对象引用。

function sqlalchemy.ext.automap.automap_base(declarative_base: Type[Any] | None = None, **kw: Any) Any

生成一个声明性自动映射基类。

此函数生成一个新的基类,它是 AutomapBase 类以及由 declarative_base() 生成的声明性基类的产物。

除了 declarative_base 之外的所有参数都是关键字参数,它们将直接传递给 declarative_base() 函数。

参数:
  • declarative_base – 由 declarative_base() 生成的现有类。当传递此参数时,该函数不再调用 declarative_base() 本身,所有其他关键字参数都会被忽略。

  • **kw – 关键字参数将传递给 declarative_base()

class sqlalchemy.ext.automap.AutomapBase

“自动映射”架构的基类。

AutomapBase 类可以与由 declarative_base() 函数生成的“声明性基类”类进行比较。在实践中,AutomapBase 类始终与实际的声明性基类一起用作 mixin。

通常使用 automap_base() 函数实例化新的可子类化 AutomapBase

另请参阅

自动映射

attribute sqlalchemy.ext.automap.AutomapBase.by_module: ClassVar[ByModuleProperties]

一个 Properties 实例,它包含一个分层结构的点分隔模块名称,这些名称链接到类。

此集合是 AutomapBase.classes 集合的替代方案,在使用 AutomapBase.prepare.modulename_for_table 参数时很有用,该参数将对生成的类应用不同的 __module__ 属性。

自动映射生成的类的默认 __module__sqlalchemy.ext.automap;要使用 AutomapBase.by_module 访问此命名空间,如下所示

User = Base.by_module.sqlalchemy.ext.automap.User

如果一个类的 __module__mymodule.account,访问此命名空间如下所示

MyClass = Base.by_module.mymodule.account.MyClass

版本 2.0 新版功能。

attribute sqlalchemy.ext.automap.AutomapBase.classes: ClassVar[Properties[Type[Any]]]

一个包含类的 Properties 实例。

此对象的行为与表的 .c 集合非常类似。类在给定的名称下存在,例如

Base = automap_base()
Base.prepare(autoload_with=some_engine)

User, Address = Base.classes.User, Base.classes.Address

对于与 Properties 的方法名称重叠的类名,例如 items(),还支持 getitem 形式

Item = Base.classes["items"]
attribute sqlalchemy.ext.automap.AutomapBase.metadata: ClassVar[MetaData]

引用将用于新的 Table 对象的 MetaData 集合。

另请参阅

访问表和元数据

classmethod sqlalchemy.ext.automap.AutomapBase.prepare(autoload_with: Engine | None = None, engine: Any | None = None, reflect: bool = False, schema: str | None = None, classname_for_table: PythonNameForTableType | None = None, modulename_for_table: PythonNameForTableType | None = None, collection_class: Any | None = None, name_for_scalar_relationship: NameForScalarRelationshipType | None = None, name_for_collection_relationship: NameForCollectionRelationshipType | None = None, generate_relationship: GenerateRelationshipType | None = None, reflection_options: Dict[_KT, _VT] | immutabledict[_KT, _VT] = {}) None

MetaData 中提取映射类和关系并执行映射。

有关完整文档和示例,请参见 基本用法

参数:
function sqlalchemy.ext.automap.classname_for_table(base: Type[Any], tablename: str, table: Table) str

返回应使用的类名,给出表的名称。

默认实现是

return str(tablename)

可以使用 AutomapBase.prepare.classname_for_table 参数指定备用实现。

参数:
返回值:

一个字符串类名。

注意

在 Python 2 中,用于类名的字符串 **必须** 是一个非 Unicode 对象,例如 str() 对象。 Table.name 属性通常是 Python unicode 子类,因此应该将 str() 函数应用于此名称,然后考虑任何非 ASCII 字符。

function sqlalchemy.ext.automap.name_for_scalar_relationship(base: Type[Any], local_cls: Type[Any], referred_cls: Type[Any], constraint: ForeignKeyConstraint) str

返回用于从一个类引用另一个类的属性名,用于标量对象引用。

默认实现是

return referred_cls.__name__.lower()

可以使用 AutomapBase.prepare.name_for_scalar_relationship 参数指定备用实现。

参数:
  • base – 进行准备的 AutomapBase 类。

  • local_cls – 要在本地端映射的类。

  • referred_cls – 要在引用端映射的类。

  • constraint – 正在检查以生成此关系的 ForeignKeyConstraint

function sqlalchemy.ext.automap.name_for_collection_relationship(base: Type[Any], local_cls: Type[Any], referred_cls: Type[Any], constraint: ForeignKeyConstraint) str

返回用于从一个类引用另一个类的属性名,用于集合引用。

默认实现是

return referred_cls.__name__.lower() + "_collection"

可以使用 AutomapBase.prepare.name_for_collection_relationship 参数指定备用实现。

参数:
  • base – 进行准备的 AutomapBase 类。

  • local_cls – 要在本地端映射的类。

  • referred_cls – 要在引用端映射的类。

  • constraint – 正在检查以生成此关系的 ForeignKeyConstraint

函数 sqlalchemy.ext.automap.generate_relationship(base: Type[Any], direction: RelationshipDirection, return_fn: Callable[..., Relationship[Any]] | Callable[..., ORMBackrefArgument], attrname: str, local_cls: Type[Any], referred_cls: Type[Any], **kw: Any) Relationship[Any] | ORMBackrefArgument

为两个映射类生成 relationship()backref()

可以使用 AutomapBase.prepare.generate_relationship 参数指定此函数的替代实现。

此函数的默认实现如下所示

if return_fn is backref:
    return return_fn(attrname, **kw)
elif return_fn is relationship:
    return return_fn(referred_cls, **kw)
else:
    raise TypeError("Unknown relationship function: %s" % return_fn)
参数:
  • base – 进行准备的 AutomapBase 类。

  • direction – 指示关系的“方向”;这将是 ONETOMANYMANYTOONEMANYTOMANY 之一。

  • return_fn – 用于创建关系的默认函数。这将是 relationship()backref()backref() 函数的结果将用于在第二步生成一个新的 relationship(),因此,如果使用自定义关系函数,则用户定义的实现必须正确区分这两个函数。

  • attrname – 将此关系分配到的属性名称。如果 generate_relationship.return_fn 的值为 backref() 函数,则此名称是分配给反向引用者的名称。

  • local_cls – 此关系或反向引用者在本地存在的“本地”类。

  • referred_cls – 此关系或反向引用者引用的“被引用”类。

  • **kw – 所有附加的关键字参数都将传递给该函数。

返回值:

generate_relationship.return_fn 参数决定的 relationship()backref() 结构。