Manipulación de datos con el ORM#

  • Ultima modificación: Mar 6, 2024 | YouTube

Preparación#

[1]:
from sqlalchemy import Column, ForeignKey, Integer, String
from sqlalchemy.orm import declarative_base, relationship

Base = declarative_base()


class User(Base):
    __tablename__ = "user_account"
    id = Column(Integer, primary_key=True)
    name = Column(String(30))
    fullname = Column(String)
    addresses = relationship(
        "Address", back_populates="user", cascade="all, delete-orphan"
    )

    def __repr__(self):
        return f"User(id={self.id!r}, name={self.name!r}, fullname={self.fullname!r})"


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)
    user = relationship("User", back_populates="addresses")

    def __repr__(self):
        return f"Address(id={self.id!r}, email_address={self.email_address!r})"
[2]:
from sqlalchemy import create_engine

engine = create_engine(
    "sqlite+pysqlite:///:memory:",
    echo=False,
    future=True,
)
[3]:
Base.metadata.create_all(engine)
[4]:
from sqlalchemy.orm import Session

with Session(engine) as session:

    spongebob = User(
        name="spongebob",
        fullname="Spongebob Squarepants",
        addresses=[Address(email_address="spongebob@sqlalchemy.org")],
    )

    sandy = User(
        name="sandy",
        fullname="Sandy Cheeks",
        addresses=[
            Address(email_address="sandy@sqlalchemy.org"),
            Address(email_address="sandy@squirrelpower.org"),
        ],
    )

    patrick = User(
        name="patrick",
        fullname="Patrick Star",
    )

    session.add_all(
        [
            spongebob,
            sandy,
            patrick,
        ]
    )

    session.commit()

Adición de objetos a una sesión#

[5]:
squidward = User(name="squidward", fullname="Squidward Tentacles")
krabs = User(name="ehkrabs", fullname="Eugene H. Krabs")
[6]:
squidward
[6]:
User(id=None, name='squidward', fullname='Squidward Tentacles')
[7]:
krabs
[7]:
User(id=None, name='ehkrabs', fullname='Eugene H. Krabs')
[8]:
session = Session(engine)
session.add(squidward)
session.add(krabs)

#
# Los objetos pendientes por insertar se ven en session.new
#
session.new
[8]:
IdentitySet([User(id=None, name='squidward', fullname='Squidward Tentacles'), User(id=None, name='ehkrabs', fullname='Eugene H. Krabs')])
[9]:
#
# Cuando se emiten los cambios a la BD se hace un flush.
#
session.flush()
[10]:
#
# No hay cambios pendientes
#
session.new
[10]:
IdentitySet([])

Claves primarias autogeneradas#

[11]:
squidward.id
[11]:
4
[12]:
krabs.id
[12]:
5

Obtención de objetos por la clave primaria#

[13]:
some_squidward = session.get(User, 4)
some_squidward
[13]:
User(id=4, name='squidward', fullname='Squidward Tentacles')
[14]:
some_squidward is squidward
[14]:
True

Commiting#

[15]:
session.commit()

Actualización de objetos#

[16]:
from sqlalchemy import select

sandy = session.execute(select(User).filter_by(name="sandy")).scalar_one()
sandy
[16]:
User(id=2, name='sandy', fullname='Sandy Cheeks')
[17]:
#
# Se altera el atributo de un objeto
#
sandy.fullname = "Sandy Squirrel"
[18]:
#
# El objeto pertenece a una colección "dirty"
#
sandy in session.dirty
[18]:
True
[19]:
sandy_fullname = session.execute(select(User.fullname).where(User.id == 2)).scalar_one()

print(sandy_fullname)
Sandy Squirrel
[20]:
sandy in session.dirty
[20]:
False

UPDATE en el ORM#

[21]:
from sqlalchemy import update

session.execute(
    update(User)
    .where(User.name == "sandy")
    .values(fullname="Sandy Squirrel Extraordinaire")
)
[21]:
<sqlalchemy.engine.cursor.CursorResult at 0x110b6a4c0>
[22]:
sandy.fullname
[22]:
'Sandy Squirrel Extraordinaire'

Borrado de objetos ORM#

[23]:
patrick = session.get(User, 3)
[24]:
session.delete(patrick)
[25]:
session.execute(select(User).where(User.name == "patrick")).first()
[26]:
patrick in session
[26]:
False
[27]:
from sqlalchemy import delete

squidward = session.get(User, 4)

session.execute(delete(User).where(User.name == "squidward"))
[27]:
<sqlalchemy.engine.cursor.CursorResult at 0x110b88ac0>
[28]:
squidward in session
[28]:
False

Rolling back#

[29]:
session.rollback()
[30]:
sandy.__dict__
[30]:
{'_sa_instance_state': <sqlalchemy.orm.state.InstanceState at 0x110b464c0>}
[31]:
sandy.fullname
[31]:
'Sandy Cheeks'
[32]:
sandy.__dict__
[32]:
{'_sa_instance_state': <sqlalchemy.orm.state.InstanceState at 0x110b464c0>,
 'id': 2,
 'name': 'sandy',
 'fullname': 'Sandy Cheeks'}
[33]:
patrick in session
[33]:
True
[34]:
session.execute(select(User).where(User.name == "patrick")).scalar_one() is patrick
[34]:
True

Cerrado de una sesión#

[35]:
session.close()