Automap¶
Определение расширения системы sqlalchemy.ext.declarative
, которое автоматически генерирует отображенные классы и отношения на основе схемы базы данных, обычно, хотя и не обязательно, отражаемой.
Предполагается, что система AutomapBase
обеспечивает быстрое и модернизированное решение проблемы, которую пытается решить и известная SQLSoup, - быструю и рудиментарную генерацию объектной модели из существующей базы данных «на лету». Решая проблему строго на уровне конфигурации маппера и полностью интегрируясь с существующими технологиями декларативных классов, AutomapBase
стремится обеспечить хорошо интегрированный подход к проблеме оперативной автогенерации специальных маппингов.
Совет
Расширение Automap ориентировано на подход «нулевого объявления», когда полная модель 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="foo@bar.com", 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
декларативных базовых классов; затем для каждого жизнеспособного Table
внутри MetaData
будет автоматически сгенерирован новый сопоставленный класс. Объекты ForeignKeyConstraint
, связывающие различные таблицы между собой, будут использованы для создания новых двунаправленных объектов relationship()
между классами. Классы и связи следуют стандартной схеме именования, которую мы можем настраивать. На данный момент наше базовое отображение, состоящее из связанных классов User
и Address
, готово к использованию традиционным способом.
Примечание
Под жизнеспособной мы подразумеваем, что для сопоставления таблица должна иметь первичный ключ. Кроме того, если таблица определяется как чистая ассоциативная таблица между двумя другими таблицами, то она не будет отображаться напрямую, а будет сконфигурирована как таблица «многие-ко-многим» между отображениями двух ссылающихся таблиц.
Генерация отображений на основе существующих метаданных¶
В automap_base()
можно передать заранее объявленный объект MetaData
. Этот объект может быть сконструирован любым способом, в том числе программно, из сериализованного файла или из самого отражения с помощью 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, Address, Order = Base.classes.user, Base.classes.address,\
Base.classes.user_order
Генерация отображений из нескольких схем¶
Метод AutomapBase.prepare()
при использовании отражения может отражать таблицы не более чем из одной схемы, используя параметр AutomapBase.prepare.schema
для указания имени схемы, из которой производится отражение. Чтобы заполнить AutomapBase
таблицами из нескольких схем, метод AutomapBase.prepare()
может быть вызван несколько раз, каждый раз передавая параметру AutomapBase.prepare.schema
другое имя. Метод AutomapBase.prepare()
ведет внутренний список объектов Table
, которые уже были отображены, и добавляет новые отображения только для тех объектов Table
, которые появились с момента последнего запуска AutomapBase.prepare()
:
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
; сюда помещаются только классы, которым не было задано явное модульное имя, поскольку коллекция не может представлять одноименные классы по отдельности.
В приведенном выше примере, если база данных содержит таблицу с именем accounts
во всех трех схемах: схеме по умолчанию, схеме test_schema
и схеме test_schema_2
, будут доступны три отдельных класса в виде:
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
. Поэтому, как правило, использовать AutomapBase.by_module
необходимо только при наличии явных соглашений __module__
.
Указание классов в явном виде¶
Совет
Если предполагается, что явные классы будут занимать важное место в приложении, то вместо них следует использовать DeferredReflection
.
Расширение automap
позволяет определять классы в явном виде, подобно тому, как это делается в классе DeferredReflection
. Классы, расширяемые из AutomapBase
, действуют как обычные декларативные классы, но не отображаются сразу после их создания, а отображаются при вызове AutomapBase.prepare()
. Метод AutomapBase.prepare()
будет использовать созданные нами классы в зависимости от имени таблицы, которую мы используем. Если наша схема содержит таблицы user
и address
, то мы можем определить один или оба класса, которые будут использоваться:
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
)
Из приведенного выше отображения мы теперь будем иметь классы User
и Address
, где коллекция из User
в Address
называется User.addresses
:
User, Address = Base.classes.User, Base.classes.Address
u1 = User(addresses=[Address(email="foo@bar.com")])
Выявление взаимосвязей¶
Подавляющее большинство задач, решаемых с помощью automap, заключается в генерации структур relationship()
на основе внешних ключей. Механизм, по которому это работает для отношений «многие-к-одному» и «один-ко-многим», выглядит следующим образом:
Заданный
Table
, о котором известно, что он сопоставлен с определенным классом, проверяется на наличие объектовForeignKeyConstraint
.Из каждого
ForeignKeyConstraint
присутствующий удаленный объектTable
сопоставляется с классом, к которому он должен быть сопоставлен, если таковой имеется, в противном случае он пропускается.Поскольку рассматриваемый нами
ForeignKeyConstraint
соответствует ссылке из непосредственного сопоставленного класса, отношение будет установлено как многие-к-одному, ссылающееся на сопоставленный класс; на сопоставленном классе будет создана соответствующая обратная ссылка один-ко-многим, ссылающаяся на данный класс.Если какой-либо из столбцов, входящих в
ForeignKeyConstraint
, не является нулевым (например,nullable=False
), то к аргументам ключевого словаrelationship.cascade
, передаваемым в отношение или обратную ссылку, будет добавлен аргумент ключевого словаall, delete-orphan
. Если вForeignKeyConstraint
сообщается, чтоForeignKeyConstraint.ondelete
установлен флагCASCADE
для not null илиSET NULL
для nullable набора столбцов, то в наборе аргументов ключевых слов отношения устанавливается флагrelationship.passive_deletes
, равныйTrue
. Заметим, что не все бэкенды поддерживают отражение ON DELETE.Имена отношений определяются с помощью вызываемых функций
AutomapBase.prepare.name_for_scalar_relationship
иAutomapBase.prepare.name_for_collection_relationship
. Важно отметить, что при именовании отношений по умолчанию имя выводится из имени реального класса. Если вы задали конкретному классу явное имя, объявив его, или указали альтернативную схему именования классов, то именно от этого имени будет зависеть имя отношения.Классы проверяются на наличие существующего сопоставленного свойства, соответствующего этим именам. Если таковое обнаруживается на одной стороне, но отсутствует на другой,
AutomapBase
пытается создать отношение на отсутствующей стороне, а затем использует параметрrelationship.back_populates
, чтобы указать новое отношение на другую сторону.В обычном случае, когда ни на одной из сторон нет отношений,
AutomapBase.prepare()
создаетrelationship()
на стороне «многие-к-одному» и сопоставляет его с другим с помощью параметраrelationship.backref
.Производство
relationship()
и, опционально,backref()
передается функцииAutomapBase.prepare.generate_relationship
, которая может быть поставлена конечным пользователем для дополнения аргументов, передаваемых вrelationship()
илиbackref()
, или для использования собственных реализаций этих функций.
Аргументы пользовательских отношений¶
Хук AutomapBase.prepare.generate_relationship
может быть использован для добавления параметров к отношениям. В большинстве случаев для возврата объекта можно воспользоваться существующей функцией generate_relationship()
, дополнив заданный словарь ключевых слов собственными аргументами.
Ниже показано, как передать опции relationship.cascade
и relationship.passive_deletes
всем отношениям «один-ко-многим»:
from sqlalchemy.ext.automap import generate_relationship
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
. Процесс создания таких отношений выглядит следующим образом:
Заданный
Table
проверяется на наличие объектовForeignKeyConstraint
, прежде чем ему будет присвоен какой-либо сопоставленный класс.Если таблица содержит два и ровно два объекта
ForeignKeyConstraint
, и все столбцы внутри этой таблицы являются членами этих двух объектовForeignKeyConstraint
, то таблица считается «вторичной», и не будет отображаться напрямую.Двум (или одной, для самореферентных) внешним таблицам, на которые ссылается
Table
, ставятся в соответствие классы, с которыми они будут сопоставлены, если таковые имеются.Если отображенные классы для обеих сторон расположены, то между ними создается двунаправленная пара многие-ко-многим
relationship()
/backref()
.Логика переопределения для many-to-many работает так же, как и для one-to-many/ many-to-one; функция
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',
}
Внешний ключ от Engineer
к Employee
используется не для отношения, а для установления объединенного наследования между двумя классами.
Обратите внимание, что это означает, что automap не будет генерировать любые отношения для внешних ключей, которые связывают подкласс с суперклассом. Если в отображении есть реальные связи от подкласса к суперклассу, то они должны быть явными. Ниже, поскольку у нас есть два отдельных внешних ключа от Engineer
к Employee
, нам необходимо задать как нужное нам отношение, так и 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
Выше, при наличии в основном полных отображений User
и Address
, ForeignKey
, определенный нами на Address.user_id
, позволил сформировать на сопоставленных классах пары двунаправленных отношений Address.user
и User.address_collection
.
Заметим, что при подклассификации AutomapBase
обязателен метод AutomapBase.prepare()
, если его не вызвать, то объявленные нами классы окажутся в не отображенном состоянии.
Определения перехватывающих колонок¶
Объекты MetaData
и Table
поддерживают крючок событий 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
.
См.также
Автоматизация схем именования столбцов из отраженных таблиц - в документации по отображению ORM
Справочник по API¶
Object Name | Description |
---|---|
automap_base([declarative_base], **kw) |
Создать декларативную базу автоматов. |
Базовый класс для схемы «automap». |
|
classname_for_table(base, tablename, table) |
Возвращает имя класса, который должен быть использован при задании имени таблицы. |
generate_relationship(base, direction, return_fn, attrname, ..., **kw) |
Генерировать |
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: Optional[Type[Any]] = 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¶
Базовый класс для схемы «automap».
Класс
AutomapBase
можно сравнить с «декларативным базовым» классом, который создается функциейdeclarative_base()
. На практике классAutomapBase
всегда используется в качестве миксина наряду с реальной декларативной базой.Новый подклассифицируемый
AutomapBase
обычно инстанцируется с помощью функцииautomap_base()
.См.также
-
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
-
attribute
sqlalchemy.ext.automap.AutomapBase.
metadata: ClassVar[MetaData]¶ Ссылается на коллекцию
MetaData
, которая будет использоваться для новых объектовTable
.См.также
-
classmethod
sqlalchemy.ext.automap.AutomapBase.
prepare(autoload_with: Optional[Engine] = None, engine: Optional[Any] = None, reflect: bool = False, schema: Optional[str] = None, classname_for_table: Optional[PythonNameForTableType] = None, modulename_for_table: Optional[PythonNameForTableType] = None, collection_class: Optional[Any] = None, name_for_scalar_relationship: Optional[NameForScalarRelationshipType] = None, name_for_collection_relationship: Optional[NameForCollectionRelationshipType] = None, generate_relationship: Optional[GenerateRelationshipType] = None, reflection_options: Union[Dict[_KT, _VT], immutabledict[_KT, _VT]] = {}) None ¶ Извлечение сопоставленных классов и отношений из
MetaData
и выполнение сопоставления.Полная документация и примеры приведены в разделе Базовое использование.
- Параметры:
autoload_with –
Engine
илиConnection
, с помощью которого выполняется отражение схемы; при указании метода в области действия этого метода будет вызван методMetaData.reflect()
.engine – legacy; use
AutomapBase.autoload_with
. Используется для указанияEngine
илиConnection
, с помощью которых следует отражать таблицы, еслиAutomapBase.reflect
имеет значение True. … deprecated:: 1.4 ПараметрAutomapBase.prepare.engine
является устаревшим и будет удален в одном из следующих выпусков. Пожалуйста, используйте параметрAutomapBase.prepare.autoload_with
.reflect – legacy; use
AutomapBase.autoload_with
. Указывает на необходимость вызоваMetaData.reflect()
. … deprecated:: 1.4 ПараметрAutomapBase.prepare.reflect
является устаревшим и будет удален в будущем выпуске. Отражение включается, когда передаетсяAutomapBase.prepare.autoload_with
.classname_for_table – вызываемая функция, которая будет использоваться для создания новых имен классов при заданном имени таблицы. По умолчанию принимает значение
classname_for_table()
.modulename_for_table – вызываемая функция, которая будет использоваться для получения эффективного значения
__module__
для внутреннего класса, что позволяет использовать в одной базе automap несколько одноименных классов, которые будут находиться в разных «модулях». По умолчанию имеет значениеNone
, что указывает на то, что__module__
не будет задаваться явно; среда выполнения Python будет использовать для этих классов значениеsqlalchemy.ext.automap
. При назначении__module__
сгенерированным классам доступ к ним можно получить на основе имен модулей, разделенных точками, с помощью коллекцииAutomapBase.by_module
. Классы, которым явно назначен__module_
с помощью этого хука, не помещаются в коллекциюAutomapBase.classes
, а только вAutomapBase.by_module
. … версия добавлена:: 2.0 .. seealso:: Генерация отображений из нескольких схемname_for_scalar_relationship – вызываемая функция, которая будет использоваться для создания имен отношений для скалярных отношений. По умолчанию имеет значение
name_for_scalar_relationship()
.name_for_collection_relationship – вызываемая функция, которая будет использоваться для создания имен отношений для отношений, ориентированных на коллекции. По умолчанию имеет значение
name_for_collection_relationship()
.generate_relationship – вызываемая функция, которая будет использоваться для фактической генерации конструкций
relationship()
иbackref()
. По умолчанию используетсяgenerate_relationship()
.collection_class – класс коллекции Python, который будет использоваться при создании нового объекта
relationship()
, представляющего коллекцию. По умолчанию принимается значениеlist
.schema – Имя схемы, отражаемое при отражении таблиц с помощью параметра
AutomapBase.prepare.autoload_with
. Это имя передается в параметрMetaData.reflect.schema
параметраMetaData.reflect()
. Если это имя опущено, то используется схема по умолчанию, используемая при подключении к базе данных. … note:: ПараметрAutomapBase.prepare.schema
поддерживает отражение только одной схемы за раз. Для включения таблиц из многих схем необходимо использовать несколько вызововAutomapBase.prepare()
. Обзор многосхемной автоматизации, включая использование дополнительных соглашений об именовании для разрешения конфликтов имен таблиц, приведен в разделе Генерация отображений из нескольких схем. … versionadded:: 2.0AutomapBase.prepare()
поддерживает прямой вызов любое количество раз, отслеживая таблицы, которые уже были обработаны, чтобы не обрабатывать их второй раз.reflection_options – Когда он присутствует, этот словарь опций будет передан в
MetaData.reflect()
для предоставления общих опций, специфичных для отражения, таких какonly
, и/или опций, специфичных для диалекта, таких какoracle_resolve_synonyms
. … versionadded:: 1.4
-
attribute
- function sqlalchemy.ext.automap.classname_for_table(base: Type[Any], tablename: str, table: Table) str ¶
Возвращает имя класса, который должен быть использован при задании имени таблицы.
По умолчанию реализовано:
return str(tablename)
Альтернативные реализации могут быть указаны с помощью параметра
AutomapBase.prepare.classname_for_table
.- Параметры:
base – класс
AutomapBase
, выполняющий подготовку.tablename – строковое имя
Table
.table – сам объект
Table
.
- Результат:
строковое имя класса. …примечание:: В Python 2 строка, используемая для имени класса, должна быть неюникодным объектом, например, объектом
str()
. Атрибут.name
объектаTable
обычно является подклассом 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
, которая проверяется для получения этого отношения.
- function sqlalchemy.ext.automap.generate_relationship(base: Type[Any], direction: RelationshipDirection, return_fn: Union[Callable[..., Relationship[Any]], Callable[..., ORMBackrefArgument]], attrname: str, local_cls: Type[Any], referred_cls: Type[Any], **kw: Any) Union[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 – указывают «направление» связи; это будет одно из
ONETOMANY
,MANYTOONE
,MANYTOMANY
.return_fn – функция, которая по умолчанию используется для создания отношения. Это будет либо
relationship()
, либоbackref()
. Результат функцииbackref()
будет использован для создания новойrelationship()
на втором шаге, поэтому очень важно, чтобы пользовательские реализации правильно различали эти две функции, если используется пользовательская функция отношения.attrname – имя атрибута, которому присваивается данное отношение. Если значением
generate_relationship.return_fn
является функцияbackref()
, то это имя является именем, которому присваивается обратная ссылка.local_cls – «локальный» класс, для которого данное отношение или обратная ссылка будет присутствовать локально.
referred_cls – «ссылающийся» класс, на который ссылается данное отношение или обратная ссылка.
**kw – все дополнительные аргументы ключевого слова передаются в функцию.
- Результат:
конструкцию
relationship()
илиbackref()
, что диктуется параметромgenerate_relationship.return_fn
.