147 lines
5.3 KiB
Python
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())
|