You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

333 lines
10KB

  1. # orm/__init__.py
  2. # Copyright (C) 2005-2021 the SQLAlchemy authors and contributors
  3. # <see AUTHORS file>
  4. #
  5. # This module is part of SQLAlchemy and is released under
  6. # the MIT License: http://www.opensource.org/licenses/mit-license.php
  7. """
  8. Functional constructs for ORM configuration.
  9. See the SQLAlchemy object relational tutorial and mapper configuration
  10. documentation for an overview of how this module is used.
  11. """
  12. from . import exc
  13. from . import mapper as mapperlib
  14. from . import strategy_options
  15. from .attributes import AttributeEvent
  16. from .attributes import InstrumentedAttribute
  17. from .attributes import Mapped
  18. from .attributes import QueryableAttribute
  19. from .context import QueryContext
  20. from .decl_api import as_declarative
  21. from .decl_api import declarative_base
  22. from .decl_api import declarative_mixin
  23. from .decl_api import DeclarativeMeta
  24. from .decl_api import declared_attr
  25. from .decl_api import has_inherited_table
  26. from .decl_api import registry
  27. from .decl_api import synonym_for
  28. from .descriptor_props import CompositeProperty
  29. from .descriptor_props import SynonymProperty
  30. from .identity import IdentityMap
  31. from .instrumentation import ClassManager
  32. from .interfaces import EXT_CONTINUE
  33. from .interfaces import EXT_SKIP
  34. from .interfaces import EXT_STOP
  35. from .interfaces import InspectionAttr
  36. from .interfaces import InspectionAttrInfo
  37. from .interfaces import MANYTOMANY
  38. from .interfaces import MANYTOONE
  39. from .interfaces import MapperProperty
  40. from .interfaces import NOT_EXTENSION
  41. from .interfaces import ONETOMANY
  42. from .interfaces import PropComparator
  43. from .loading import merge_frozen_result
  44. from .loading import merge_result
  45. from .mapper import class_mapper
  46. from .mapper import configure_mappers
  47. from .mapper import Mapper
  48. from .mapper import reconstructor
  49. from .mapper import validates
  50. from .properties import ColumnProperty
  51. from .query import AliasOption
  52. from .query import FromStatement
  53. from .query import Query
  54. from .relationships import foreign
  55. from .relationships import RelationshipProperty
  56. from .relationships import remote
  57. from .scoping import scoped_session
  58. from .session import close_all_sessions
  59. from .session import make_transient
  60. from .session import make_transient_to_detached
  61. from .session import object_session
  62. from .session import ORMExecuteState
  63. from .session import Session
  64. from .session import sessionmaker
  65. from .session import SessionTransaction
  66. from .state import AttributeState
  67. from .state import InstanceState
  68. from .strategy_options import Load
  69. from .unitofwork import UOWTransaction
  70. from .util import aliased
  71. from .util import Bundle
  72. from .util import CascadeOptions
  73. from .util import join
  74. from .util import LoaderCriteriaOption
  75. from .util import object_mapper
  76. from .util import outerjoin
  77. from .util import polymorphic_union
  78. from .util import was_deleted
  79. from .util import with_parent
  80. from .util import with_polymorphic
  81. from .. import sql as _sql
  82. from .. import util as _sa_util
  83. from ..util.langhelpers import public_factory
  84. def create_session(bind=None, **kwargs):
  85. r"""Create a new :class:`.Session`
  86. with no automation enabled by default.
  87. This function is used primarily for testing. The usual
  88. route to :class:`.Session` creation is via its constructor
  89. or the :func:`.sessionmaker` function.
  90. :param bind: optional, a single Connectable to use for all
  91. database access in the created
  92. :class:`~sqlalchemy.orm.session.Session`.
  93. :param \*\*kwargs: optional, passed through to the
  94. :class:`.Session` constructor.
  95. :returns: an :class:`~sqlalchemy.orm.session.Session` instance
  96. The defaults of create_session() are the opposite of that of
  97. :func:`sessionmaker`; ``autoflush`` and ``expire_on_commit`` are
  98. False, ``autocommit`` is True. In this sense the session acts
  99. more like the "classic" SQLAlchemy 0.3 session with these.
  100. Usage::
  101. >>> from sqlalchemy.orm import create_session
  102. >>> session = create_session()
  103. It is recommended to use :func:`sessionmaker` instead of
  104. create_session().
  105. """
  106. if kwargs.get("future", False):
  107. kwargs.setdefault("autocommit", False)
  108. else:
  109. kwargs.setdefault("autocommit", True)
  110. kwargs.setdefault("autoflush", False)
  111. kwargs.setdefault("expire_on_commit", False)
  112. return Session(bind=bind, **kwargs)
  113. with_loader_criteria = public_factory(LoaderCriteriaOption, ".orm")
  114. relationship = public_factory(RelationshipProperty, ".orm.relationship")
  115. @_sa_util.deprecated_20("relation", "Please use :func:`.relationship`.")
  116. def relation(*arg, **kw):
  117. """A synonym for :func:`relationship`."""
  118. return relationship(*arg, **kw)
  119. def dynamic_loader(argument, **kw):
  120. """Construct a dynamically-loading mapper property.
  121. This is essentially the same as
  122. using the ``lazy='dynamic'`` argument with :func:`relationship`::
  123. dynamic_loader(SomeClass)
  124. # is the same as
  125. relationship(SomeClass, lazy="dynamic")
  126. See the section :ref:`dynamic_relationship` for more details
  127. on dynamic loading.
  128. """
  129. kw["lazy"] = "dynamic"
  130. return relationship(argument, **kw)
  131. column_property = public_factory(ColumnProperty, ".orm.column_property")
  132. composite = public_factory(CompositeProperty, ".orm.composite")
  133. def backref(name, **kwargs):
  134. """Create a back reference with explicit keyword arguments, which are the
  135. same arguments one can send to :func:`relationship`.
  136. Used with the ``backref`` keyword argument to :func:`relationship` in
  137. place of a string argument, e.g.::
  138. 'items':relationship(
  139. SomeItem, backref=backref('parent', lazy='subquery'))
  140. .. seealso::
  141. :ref:`relationships_backref`
  142. """
  143. return (name, kwargs)
  144. def deferred(*columns, **kw):
  145. r"""Indicate a column-based mapped attribute that by default will
  146. not load unless accessed.
  147. :param \*columns: columns to be mapped. This is typically a single
  148. :class:`_schema.Column` object,
  149. however a collection is supported in order
  150. to support multiple columns mapped under the same attribute.
  151. :param raiseload: boolean, if True, indicates an exception should be raised
  152. if the load operation is to take place.
  153. .. versionadded:: 1.4
  154. .. seealso::
  155. :ref:`deferred_raiseload`
  156. :param \**kw: additional keyword arguments passed to
  157. :class:`.ColumnProperty`.
  158. .. seealso::
  159. :ref:`deferred`
  160. """
  161. return ColumnProperty(deferred=True, *columns, **kw)
  162. def query_expression(default_expr=_sql.null()):
  163. """Indicate an attribute that populates from a query-time SQL expression.
  164. :param default_expr: Optional SQL expression object that will be used in
  165. all cases if not assigned later with :func:`_orm.with_expression`.
  166. E.g.::
  167. from sqlalchemy.sql import literal
  168. class C(Base):
  169. #...
  170. my_expr = query_expression(literal(1))
  171. .. versionadded:: 1.3.18
  172. .. versionadded:: 1.2
  173. .. seealso::
  174. :ref:`mapper_querytime_expression`
  175. """
  176. prop = ColumnProperty(default_expr)
  177. prop.strategy_key = (("query_expression", True),)
  178. return prop
  179. mapper = public_factory(Mapper, ".orm.mapper")
  180. synonym = public_factory(SynonymProperty, ".orm.synonym")
  181. def clear_mappers():
  182. """Remove all mappers from all classes.
  183. .. versionchanged:: 1.4 This function now locates all
  184. :class:`_orm.registry` objects and calls upon the
  185. :meth:`_orm.registry.dispose` method of each.
  186. This function removes all instrumentation from classes and disposes
  187. of their associated mappers. Once called, the classes are unmapped
  188. and can be later re-mapped with new mappers.
  189. :func:`.clear_mappers` is *not* for normal use, as there is literally no
  190. valid usage for it outside of very specific testing scenarios. Normally,
  191. mappers are permanent structural components of user-defined classes, and
  192. are never discarded independently of their class. If a mapped class
  193. itself is garbage collected, its mapper is automatically disposed of as
  194. well. As such, :func:`.clear_mappers` is only for usage in test suites
  195. that re-use the same classes with different mappings, which is itself an
  196. extremely rare use case - the only such use case is in fact SQLAlchemy's
  197. own test suite, and possibly the test suites of other ORM extension
  198. libraries which intend to test various combinations of mapper construction
  199. upon a fixed set of classes.
  200. """
  201. mapperlib._dispose_registries(mapperlib._all_registries(), False)
  202. joinedload = strategy_options.joinedload._unbound_fn
  203. contains_eager = strategy_options.contains_eager._unbound_fn
  204. defer = strategy_options.defer._unbound_fn
  205. undefer = strategy_options.undefer._unbound_fn
  206. undefer_group = strategy_options.undefer_group._unbound_fn
  207. with_expression = strategy_options.with_expression._unbound_fn
  208. load_only = strategy_options.load_only._unbound_fn
  209. lazyload = strategy_options.lazyload._unbound_fn
  210. subqueryload = strategy_options.subqueryload._unbound_fn
  211. selectinload = strategy_options.selectinload._unbound_fn
  212. immediateload = strategy_options.immediateload._unbound_fn
  213. noload = strategy_options.noload._unbound_fn
  214. raiseload = strategy_options.raiseload._unbound_fn
  215. defaultload = strategy_options.defaultload._unbound_fn
  216. selectin_polymorphic = strategy_options.selectin_polymorphic._unbound_fn
  217. @_sa_util.deprecated_20("eagerload", "Please use :func:`_orm.joinedload`.")
  218. def eagerload(*args, **kwargs):
  219. """A synonym for :func:`joinedload()`."""
  220. return joinedload(*args, **kwargs)
  221. contains_alias = public_factory(AliasOption, ".orm.contains_alias")
  222. if True:
  223. from .events import AttributeEvents
  224. from .events import MapperEvents
  225. from .events import InstanceEvents
  226. from .events import InstrumentationEvents
  227. from .events import QueryEvents
  228. from .events import SessionEvents
  229. def __go(lcls):
  230. global __all__
  231. global AppenderQuery
  232. from .. import util as sa_util
  233. from . import dynamic
  234. from . import events
  235. from . import loading
  236. import inspect as _inspect
  237. from .dynamic import AppenderQuery
  238. __all__ = sorted(
  239. name
  240. for name, obj in lcls.items()
  241. if not (name.startswith("_") or _inspect.ismodule(obj))
  242. )
  243. _sa_util.preloaded.import_prefix("sqlalchemy.orm")
  244. _sa_util.preloaded.import_prefix("sqlalchemy.ext")
  245. __go(locals())