Apuntes_Python/01_curso/Modulo_4/4-4d_objetos_relacionados.py
2022-12-24 22:41:20 -03:00

147 lines
5.3 KiB
Python

# -*- coding: utf-8 -*-
"""
Construyendo relación entre objetos
.- crear columna clave foránea hacia la tabla del modelo a relacionar
.- crear relación con el modelo utilizando el constructor de relaciones llamado relationship.
.- la relación es bidireccional.
"""
# Ej. se muestra una relación uno a muchos (un autor muchos libros):
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, Sequence, ForeignKey
from sqlalchemy.orm import sessionmaker, relationship
Base = declarative_base()
class Author(Base):
__tablename__ = 'author'
id = Column(Integer, Sequence('author_id_seq'), primary_key=True)
firstname = Column(String)
lastname = Column(String)
# books = relationship("Book", order_by="Book.id", back_populates="author")
# CASCADE
books = relationship("Book", order_by="Book.id", back_populates="author",
cascade="all, delete, delete-orphan")
def __repr__(self):
return "{} {}".format(self.firstname, self.lastname)
class Book(Base):
__tablename__ = 'book'
id = Column(Integer, Sequence('book_id_seq'), primary_key=True)
isbn = Column(String)
title = Column(String)
description = Column(String)
author_id = Column(Integer, ForeignKey('author.id'))
author = relationship("Author", back_populates="books")
def __repr__(self):
return "{}".format(self.title)
"""
Trabajando con Objetos Relacionados
Se puede solicitar libros por autor o al autor por sus libros.
"""
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
# crea un autor
j_rowling = Author(firstname='Joanne', lastname='Rowling')
j_rowling.books = [Book(isbn='9788498387087',
title='Harry Potter y la Piedra Filosofal',
description='La vida de Harry Potter cambia para siempre el ...'),
Book(isbn='9788498382679',
title='Harry Potter y la camara secreta',
description='Tras derrotar una vez mas a lord Voldemort, ...')]
print(j_rowling.books[1])
print(j_rowling.books[1].title)
session.add(j_rowling)
session.commit()
j_rowling = session.query(Author).filter_by(firstname='Joanne').one()
print(j_rowling.books)
"""
Consultando Objetos Relacionados
"""
# Devuelve el autor y libro para este isbn. Los imprimimos en pantalla.
for an_author, a_book in session.query(Author, Book).filter(Author.id==Book.author_id).\
filter(Book.isbn=='9788498387087').\
all():
print(an_author)
print(a_book)
# Devuelve el autor del libro con este isbn
print(session.query(Author).join(Book).filter(Book.isbn=='9788498387087').all())
# Devuelve los autores de los libros poniendo la condición explícitamente.
print(session.query(Author).join(Book, Author.id==Book.author_id).all())
# Devuelve los autores de los libros especificando la relación de izquierda a derecha.
print(session.query(Author).join(Author.books).all())
# Devuelve los autores de los libros para una relación específica.
print(session.query(Author).join(Book, Author.books).all())
# Devuelve los autores de loslibros utilizando un string.
print(session.query(Author).join('books').all())
# Devuelve el nombre del autor del libro utilizando un filtro exists.
# Es decir, si existe algún libro del autor
stmt = exists().where(Book.author_id == Author.id)
for name,in session.query(Author.firstname).filter(stmt):
print(name)
# Devuelve el nombre del autor del libro utilizando un filtro any.
# Es decir, si el autor tiene algún libro
for name, in session.query(Author.firstname).filter(Author.books.any()):
print(name)
# Devuelve el nombre del autor del libro utilizando un filtro like,
# parecido a any solo que se le puede definir una condición,
# en este caso que el apellido del autor contenga la subcadena de texto Row.
for name, in session.query(Author.firstname).filter(Author.books.any(Author.lastname.like('%Row%'))):
print(name)
# Devuelve los libros donde el autor no se llame Joanne.
print(session.query(Book).filter(~Book.author.has(Author.firstname=='Joanne')).all())
"""
Borrando Objetos
Al borrar un autor el/los libros no se borran.
Quedando sin autor. Objetos huefanos
"""
session.delete(j_rowling)
print(session.query(Author).filter_by(firstname='Joanne').count())
print(session.query(Book).\
filter(Book.isbn.in_(['9788498387087','9788498382679'])).\
count())
session.rollback()
"""
Para borrar el objeto padre y los objetos hijos, definir el atributo
cascade con la opción “all, delete, delete-orphan”
books = relationship("Book", order_by="Book.id", back_populates="author",
cascade="all, delete, delete-orphan")
"""
del j_rowling.books[1]
print(session.query(Book).filter(Book.isbn.in_(['9788498387087',
'9788498382679'])).count())
session.delete(j_rowling)
print(session.query(Author).filter_by(firstname='Joanne').count())
print(session.query(Book).filter(Book.isbn.in_(['9788498387087',
'9788498382679'])).count())