relación sqlalchemy a través de otra (declarativa)
-
26-09-2019 - |
Pregunta
¿Alguien está familiarizado con las relaciones "Has_Many: a través" de Activerecord para los modelos? Realmente no soy un chico de Rails, pero eso es básicamente lo que estoy tratando de hacer.
Como ejemplo artificial, considere proyectos, programadores y tareas:
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy import Column, ForeignKey
from sqlalchemy.types import Integer, String, Text
from sqlalchemy.orm import relation
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class Assignment(Base):
__tablename__ = 'assignment'
id = Column(Integer, primary_key=True)
description = Column(Text)
programmer_id = Column(Integer, ForeignKey('programmer.id'))
project_id = Column(Integer, ForeignKey('project.id'))
def __init__(self, description=description):
self.description = description
def __repr__(self):
return '<Assignment("%s")>' % self.description
class Programmer(Base):
__tablename__ = 'programmer'
id = Column(Integer, primary_key=True)
name = Column(String(64))
assignments = relation("Assignment", backref='programmer')
def __init__(self, name=name):
self.name = name
def __repr__(self):
return '<Programmer("%s")>' % self.name
class Project(Base):
__tablename__ = 'project'
id = Column(Integer, primary_key=True)
name = Column(String(64))
description = Column(Text)
assignments = relation("Assignment", backref='project')
def __init__(self, name=name, description=description):
self.name = name
self.description = description
def __repr__(self):
return '<Project("%s", "%s...")>' % (self.name, self.description[:10])
engine = create_engine('sqlite://')
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
Los proyectos tienen muchas tareas.
Los programadores tienen muchas tareas. (¿atenuación?)
Pero al menos en mi oficina, los programadores también tienen muchos proyectos: me gustaría que esta relación se infiera a través de las tareas asignadas al programador.
Me gustaría que el modelo de programador tenga un "proyectos" de atributo que devuelva una lista de proyectos asociados al programador a través del modelo de asignación.
me = session.query(Programmer).filter_by(name='clay').one()
projects = session.query(Project).\
join(Project.assignments).\
join(Assignment.programmer).\
filter(Programmer.id==me.id).all()
¿Cómo puedo describir esta relación clara y simplemente usando la sintaxis declarativa de Sqlalchemy?
¡Gracias!
Solución
Hay dos formas en que veo:
Definir una relación
Programmer.projects
consecondary='assignment'
.Defino
Assignment.project
como relación yProgrammer.projects
comoassociation_proxy('assignments', 'project')
(probablemente también le gustaría definir a un creador). Ver Simplificar las relaciones de objetos de asociación Capítulo para más información.