사용 관계는 내 모델입니다 .map_id "하지만 SQLAlchemy가"Map.id == user_map.map_id 및 Map.owner_id == user_map.user_id "를 사용하여 조인하려고합니다. 조인 조건을 어떻게 지정합니까?은 다 대다 SQLAlchemy의
관계에 primaryjoin 속성을 사용하고 .join() 내부의 조건을 지정하려고했지만 성공하지 못했습니다. 미리 감사드립니다!
사용 관계는 내 모델입니다 .map_id "하지만 SQLAlchemy가"Map.id == user_map.map_id 및 Map.owner_id == user_map.user_id "를 사용하여 조인하려고합니다. 조인 조건을 어떻게 지정합니까?은 다 대다 SQLAlchemy의
관계에 primaryjoin 속성을 사용하고 .join() 내부의 조건을 지정하려고했지만 성공하지 못했습니다. 미리 감사드립니다!
코드를 기반으로 설정을 다시 작성했습니다. 나는 당신의 relationship
가 섞여 있었다고 생각합니다. 또한 sqlalchemy의 다 대다 연관 테이블에서 기본 키 (또는 PrimaryKeyConstraints
)를 거의 본 적이 없습니다. 그것은 비 Orm 관점에서 이해할 수 있지만, 내가 아는 한, 그것은 이상하거나 심지어 전혀 필요하지 않습니다.
import sqlalchemy as sa
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, sessionmaker
Base = declarative_base()
UsersXMaps = sa.Table(
'users_x_maps',
Base.metadata,
sa.Column('user', sa.Integer, sa.ForeignKey('users.id')),
sa.Column('map', sa.Integer, sa.ForeignKey('maps.id'))
)
class User(Base):
__tablename__ = 'users'
id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.String)
mail = sa.Column(sa.String, unique=True)
own_maps = relationship('Map', back_populates='owner')
maps = relationship(
'Map',
secondary=UsersXMaps,
back_populates='users'
)
def __str__(self):
return '{} ({}) with {} maps'.format(
self.name, self.mail, len(self.own_maps))
class Map(Base):
__tablename__ = 'maps'
id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.String)
owner_id = sa.Column(sa.Integer, sa.ForeignKey('users.id'))
owner = relationship('User', back_populates='own_maps')
users = relationship(
'User',
secondary=UsersXMaps,
back_populates='maps'
)
def __str__(self):
return '{} (by {})'.format(self.name, self.owner.name)
지금까지 설정; 문자열을 출력 할 때 적절한 출력을 위해 약간 확장했습니다. 또한 Map.shared_maps
관계는 실제로 User
을 나타내며 Map
이 아니므로 해당 이름도 변경했습니다.
연관 테이블을 두 클래스에 바인딩 할 때 양쪽에서 참조 할 수 있습니다 (back_populates
이 원래 정의를 덮어 쓰거나 바꾼 것처럼 보일지라도). 이렇게하면 양쪽에서 조인이 간단 해집니다.
예상대로 다음과 같은 작업을 실행 :
if __name__ == '__main__':
engine = sa.create_engine('sqlite:///usermaps.db')
sfactory = sessionmaker(engine)
session = sfactory()
Base.metadata.create_all(bind=engine)
bilbo = User(id=1, name='Bilbo', mail='[email protected]')
frodo = User(id=2, name='Frodo', mail='[email protected]')
mordor = Map(id=1, name='Mordor', owner=frodo, users=[bilbo, frodo])
gondor = Map(id=2, name='Gondor', owner=bilbo, users=[bilbo, frodo])
rohan = Map(id=3, name='Rohan', owner=bilbo, users=[bilbo, frodo])
session.add_all([frodo, bilbo, mordor, gondor, rohan])
session.commit()
print('Maps by owner:')
for owner in [bilbo, frodo]:
print(owner)
for item in session.query(Map).filter(Map.owner == owner).all():
print(' - ' + str(item))
print('Maps by users:')
for item in session.query(Map).filter(Map.users.any()).all():
print(' - ' + str(item))
출력은 다음과 같습니다
Maps by owner:
Bilbo ([email protected]) with 2 maps
- Gondor (by Bilbo)
- Rohan (by Bilbo)
Frodo ([email protected]) with 1 maps
- Mordor (by Frodo)
Maps by users:
- Mordor (by Frodo)
- Gondor (by Bilbo)
- Rohan (by Bilbo)
당신은 모든 사람들이 당신의 예제를 실행 할 수 있도록, 쿼리 코드를 게시하시기 바랍니다 수 있습니까? – jbndlr
문서에서 예제를 따라 해 보았습니까? http://docs.sqlalchemy.org/en/latest/orm/basic_relationships.html#many-to-many 매핑 테이블에 PrimaryKeyConstrain이 없어야합니다. –
@jbndlr이 질문에 쿼리 코드를 추가했습니다. –