mirror of
https://github.com/sqlalchemy/sqlalchemy.git
synced 2026-05-14 12:47:22 -04:00
update quickstart for 2.0
this is just so we can point people to something while I get around to doing the rest of the docs Change-Id: Ie818024a80ad30b76d7f7d6dc179939c246084c6
This commit is contained in:
Vendored
+60
-28
@@ -13,6 +13,11 @@ As the descriptions in this section are intentionally **very short**, please
|
||||
proceed to the full :ref:`unified_tutorial` for a much more in-depth
|
||||
description of each of the concepts being illustrated here.
|
||||
|
||||
.. versionchanged:: 2.0 The ORM Quickstart is updated for the latest
|
||||
:pep:`484`-aware features using new constructs including
|
||||
:func:`_orm.mapped_column`. At the moment, the rest of the documentation
|
||||
may not be yet updated. Features such as a new dataclass-native style
|
||||
of mapping are also not documented yet.
|
||||
|
||||
Declare Models
|
||||
---------------
|
||||
@@ -20,28 +25,29 @@ Declare Models
|
||||
Here, we define module-level constructs that will form the structures
|
||||
which we will be querying from the database. This structure, known as a
|
||||
:ref:`Declarative Mapping <orm_declarative_mapping>`, defines at once both a
|
||||
Python object model, as well as
|
||||
:term:`database metadata` that describes
|
||||
Python object model, as well as :term:`database metadata` that describes
|
||||
real SQL tables that exist, or will exist, in a particular database::
|
||||
|
||||
>>> from sqlalchemy import Column
|
||||
>>> from typing import Optional
|
||||
>>> from sqlalchemy import ForeignKey
|
||||
>>> from sqlalchemy import Integer
|
||||
>>> from sqlalchemy import String
|
||||
>>> from sqlalchemy.orm import declarative_base
|
||||
>>> from sqlalchemy.orm import DeclarativeBase
|
||||
>>> from sqlalchemy.orm import Mapped
|
||||
>>> from sqlalchemy.orm import mapped_column
|
||||
>>> from sqlalchemy.orm import relationship
|
||||
|
||||
>>> Base = declarative_base()
|
||||
>>> class Base(DeclarativeBase):
|
||||
... pass
|
||||
|
||||
>>> class User(Base):
|
||||
... __tablename__ = "user_account"
|
||||
...
|
||||
... id = Column(Integer, primary_key=True)
|
||||
... name = Column(String(30))
|
||||
... fullname = Column(String)
|
||||
... id: Mapped[int] = mapped_column(primary_key=True)
|
||||
... name: Mapped[str] = mapped_column(String(30))
|
||||
... fullname: Mapped[Optional[str]]
|
||||
...
|
||||
... addresses = relationship(
|
||||
... "Address", back_populates="user", cascade="all, delete-orphan"
|
||||
... addresses: Mapped[list["Address"]] = relationship(
|
||||
... back_populates="user", cascade="all, delete-orphan"
|
||||
... )
|
||||
...
|
||||
... def __repr__(self):
|
||||
@@ -50,25 +56,52 @@ real SQL tables that exist, or will exist, in a particular database::
|
||||
>>> class Address(Base):
|
||||
... __tablename__ = "address"
|
||||
...
|
||||
... id = Column(Integer, primary_key=True)
|
||||
... email_address = Column(String, nullable=False)
|
||||
... user_id = Column(Integer, ForeignKey("user_account.id"), nullable=False)
|
||||
... id: Mapped[int] = mapped_column(primary_key=True)
|
||||
... email_address: Mapped[str]
|
||||
... user_id: Mapped[int] = mapped_column(ForeignKey("user_account.id"))
|
||||
...
|
||||
... user = relationship("User", back_populates="addresses")
|
||||
... user: Mapped["User"] = relationship(back_populates="addresses")
|
||||
...
|
||||
... def __repr__(self):
|
||||
... return f"Address(id={self.id!r}, email_address={self.email_address!r})"
|
||||
|
||||
Above, the declarative mapping makes use of :class:`_schema.Column` objects
|
||||
to define the basic units of data storage that will be in the database.
|
||||
The :func:`_orm.relationship` construct defines linkages between two
|
||||
:term:`mapped` classes, ``User`` and ``Address`` above.
|
||||
Above, new ORM mapped classes are declared as part of a common base, which is
|
||||
configured as a user-defined class that inherits from the special
|
||||
:class:`_orm.DeclarativeBase` class. Then, the declarative mapping makes use of
|
||||
both the :class:`_orm.Mapped` type annotation construct to indicate class
|
||||
attributes that are mapped, and then makes use of the
|
||||
:func:`_orm.mapped_column` and :func:`_orm.relationship` constructs to further
|
||||
qualify the specifics of how these attributes should be mapped where necessary.
|
||||
The :func:`_orm.mapped_column` construct indicates the presence of a relational
|
||||
database column, which is also implied by default when :class:`_orm.Mapped` is
|
||||
annotated without a right-hand side value. The :func:`_orm.relationship`
|
||||
construct, by contrast, defines linkages between two :term:`mapped` classes,
|
||||
``User`` and ``Address`` above.
|
||||
|
||||
The schema contains necessary elements such as primary key constraints set up
|
||||
by the :paramref:`_schema.Column.primary_key` parameter, a
|
||||
:term:`foreign key constraint` configured using :class:`_schema.ForeignKey`
|
||||
(which is used by :func:`_orm.relationship` as well), and datatypes for columns
|
||||
including :class:`_types.Integer` and :class:`_types.String`.
|
||||
Most arguments accepted by :func:`_orm.mapped_column` align with the underlying
|
||||
construct that represents a database table column, which is the
|
||||
:class:`_schema.Column` object. The schema contains necessary elements such as
|
||||
primary key constraints set up using the
|
||||
:paramref:`_orm.mapped_column.primary_key` parameter, a
|
||||
:term:`foreign key constraint` configured using the :class:`_schema.ForeignKey`
|
||||
construct, and datatypes for columns including :class:`_types.Integer`, which
|
||||
is implied by the use of the Python ``int`` datatype, and
|
||||
:class:`_types.String`, which is implied by the use of the Python ``str``
|
||||
datatype. The "nullability" of columns by default is inferred by whether or not
|
||||
the left-hand :class:`_orm.Mapped` datatype is stated as ``Optional[<type>]``
|
||||
or not.
|
||||
|
||||
In all cases, parameters passed to :func:`_orm.mapped_column`, such as specific
|
||||
datatype specifications such as ``String(30)``, or use of the the boolean parameter
|
||||
:paramref:`_orm.mapped_column.nullable`, will supersede the annotation-implied
|
||||
configuration.
|
||||
|
||||
While the above classes include an explicitly written ``__repr__()`` method,
|
||||
which is used here to illustrate usage of the classes, there is also an
|
||||
option for methods such as ``__repr__()``, ``__eq__()`` and others to be
|
||||
generated automatically using Python dataclasses. More on dataclass mapping
|
||||
at: (the new 2.0 style dataclass documentation is TODO! but it will be great
|
||||
:) )
|
||||
|
||||
More on table metadata and an intro to ORM declared mapping is in the
|
||||
Tutorial at :ref:`tutorial_working_with_metadata`.
|
||||
@@ -84,13 +117,12 @@ purposes, we normally use a :ref:`SQLite <sqlite_toplevel>` memory-only database
|
||||
for convenience::
|
||||
|
||||
>>> from sqlalchemy import create_engine
|
||||
>>> engine = create_engine("sqlite://", echo=True, future=True)
|
||||
>>> engine = create_engine("sqlite://", echo=True)
|
||||
|
||||
.. tip::
|
||||
|
||||
The ``echo=True`` parameter indicates that SQL emitted by connections will
|
||||
be logged to standard out. ``future=True`` is to ensure we are using
|
||||
the latest SQLAlchemy :term:`2.0-style` APIs.
|
||||
be logged to standard out.
|
||||
|
||||
A full intro to the :class:`_engine.Engine` starts at :ref:`tutorial_engine`.
|
||||
|
||||
@@ -111,7 +143,7 @@ in our target SQLite database, using a method called :meth:`_schema.MetaData.cre
|
||||
...
|
||||
CREATE TABLE user_account (
|
||||
id INTEGER NOT NULL,
|
||||
name VARCHAR(30),
|
||||
name VARCHAR(30) NOT NULL,
|
||||
fullname VARCHAR,
|
||||
PRIMARY KEY (id)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user