[PYTHON] 동일한 속성을 참조하는 SQLAlchemy ORM에서 자체 참조 다 대다 관계를 어떻게 성취 할 수 있습니까?
PYTHON동일한 속성을 참조하는 SQLAlchemy ORM에서 자체 참조 다 대다 관계를 어떻게 성취 할 수 있습니까?
SQLAlchemy에 대한 선언을 사용하여 자체 참조 다 대다 관계를 구현하려고합니다.
관계는 두 사용자 간의 우정을 나타냅니다. 온라인 어떻게 든 역할이 차별화 된 자체 참조 m2m 관계를 만드는 방법 (문서 및 Google 모두에서)을 찾았습니다. 이것은이 m2m 관계에서 UserA가 UserB의 상사라는 것을 의미하므로 '부하 직원'속성에 따라 그를 나열합니다. 같은 방법으로 UserB는 '상위'아래에 UserA를 나열합니다.
이런 식으로 동일한 테이블에 역 참조를 선언 할 수 있기 때문에 문제가되지 않습니다.
subordinates = relationship('User', backref='superiors')
물론 '상위'속성은 클래스 내에서 명시 적이지 않습니다.
어쨌든, 여기 내 문제가있다 : 내가 backref를 부르고있는 것과 동일한 속성으로 역 참조하고 싶다면 어떻게해야 할까? 이렇게 :
friends = relationship('User',
secondary=friendship, #this is the table that breaks the m2m
primaryjoin=id==friendship.c.friend_a_id,
secondaryjoin=id==friendship.c.friend_b_id
backref=??????
)
A와 친구가되면 관계 역할이 동일하고 B의 친구를 호출하면 A가있는 목록을 가져와야하기 때문에 이는 의미가 있습니다. 이것은 문제가되는 코드입니다.
friendship = Table(
'friendships', Base.metadata,
Column('friend_a_id', Integer, ForeignKey('users.id'), primary_key=True),
Column('friend_b_id', Integer, ForeignKey('users.id'), primary_key=True)
)
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
friends = relationship('User',
secondary=friendship,
primaryjoin=id==friendship.c.friend_a_id,
secondaryjoin=id==friendship.c.friend_b_id,
#HELP NEEDED HERE
)
이 텍스트가 너무 많으면 죄송합니다.이 작업을 할 수있는 한 명시 적으로하고 싶습니다. 웹상에서 이것에 대한 참고 자료를 찾을 수없는 것 같습니다.
해결법
-
==============================
1.오늘 날 메일 링리스트에서 암시 한 UNION 접근 방식이 있습니다.
오늘 날 메일 링리스트에서 암시 한 UNION 접근 방식이 있습니다.
from sqlalchemy import Integer, Table, Column, ForeignKey, \ create_engine, String, select from sqlalchemy.orm import Session, relationship from sqlalchemy.ext.declarative import declarative_base Base= declarative_base() friendship = Table( 'friendships', Base.metadata, Column('friend_a_id', Integer, ForeignKey('users.id'), primary_key=True), Column('friend_b_id', Integer, ForeignKey('users.id'), primary_key=True) ) class User(Base): __tablename__ = 'users' id = Column(Integer, primary_key=True) name = Column(String) # this relationship is used for persistence friends = relationship("User", secondary=friendship, primaryjoin=id==friendship.c.friend_a_id, secondaryjoin=id==friendship.c.friend_b_id, ) def __repr__(self): return "User(%r)" % self.name # this relationship is viewonly and selects across the union of all # friends friendship_union = select([ friendship.c.friend_a_id, friendship.c.friend_b_id ]).union( select([ friendship.c.friend_b_id, friendship.c.friend_a_id] ) ).alias() User.all_friends = relationship('User', secondary=friendship_union, primaryjoin=User.id==friendship_union.c.friend_a_id, secondaryjoin=User.id==friendship_union.c.friend_b_id, viewonly=True) e = create_engine("sqlite://",echo=True) Base.metadata.create_all(e) s = Session(e) u1, u2, u3, u4, u5 = User(name='u1'), User(name='u2'), \ User(name='u3'), User(name='u4'), User(name='u5') u1.friends = [u2, u3] u4.friends = [u2, u5] u3.friends.append(u5) s.add_all([u1, u2, u3, u4, u5]) s.commit() print u2.all_friends print u5.all_friends
-
==============================
2.나는이 동일한 문제를 해결할 필요가 있었고 Friend 클래스로 User 클래스를 서브 클래 싱하고 sqlalchemy.orm.exc.FlushError로 실행하면서 자체 참조 다 대 다 관계로 꽤 많은 것을 망쳤다. 결국 자기 참조 다 대다 관계를 만드는 대신 조인 테이블 (또는 보조 테이블)을 사용하여 자체 참조 일대 다 관계를 만들었습니다.
나는이 동일한 문제를 해결할 필요가 있었고 Friend 클래스로 User 클래스를 서브 클래 싱하고 sqlalchemy.orm.exc.FlushError로 실행하면서 자체 참조 다 대 다 관계로 꽤 많은 것을 망쳤다. 결국 자기 참조 다 대다 관계를 만드는 대신 조인 테이블 (또는 보조 테이블)을 사용하여 자체 참조 일대 다 관계를 만들었습니다.
자기 참조 객체로 생각하면 일대 다 다 대다 (many to many) 다. 원래 질문에서 역 참조 문제를 해결했습니다.
당신이 그것을 실제로 보길 원한다면 나는 또한 훌륭한 예제를 가지고있다. 또한 지금은 ipiththon 노트북을 포함하는 github 형식의 요지처럼 보입니다. 산뜻한.
friendship = Table( 'friendships', Base.metadata, Column('user_id', Integer, ForeignKey('users.id'), index=True), Column('friend_id', Integer, ForeignKey('users.id')), UniqueConstraint('user_id', 'friend_id', name='unique_friendships')) class User(Base): __tablename__ = 'users' id = Column(Integer, primary_key=True) name = Column(String(255)) friends = relationship('User', secondary=friendship, primaryjoin=id==friendship.c.user_id, secondaryjoin=id==friendship.c.friend_id) def befriend(self, friend): if friend not in self.friends: self.friends.append(friend) friend.friends.append(self) def unfriend(self, friend): if friend in self.friends: self.friends.remove(friend) friend.friends.remove(self) def __repr__(self): return '<User(name=|%s|)>' % self.name
from https://stackoverflow.com/questions/9116924/how-can-i-achieve-a-self-referencing-many-to-many-relationship-on-the-sqlalchemy by cc-by-sa and MIT license
'PYTHON' 카테고리의 다른 글
[PYTHON] Mac OS X에서 파이썬을 제어하기 - 환경과 라이브러리 설정하기 (0) | 2018.10.23 |
---|---|
[PYTHON] 장고 양식 '초기'와 '바운드 데이터'의 차이점은 무엇입니까? (0) | 2018.10.23 |
[PYTHON] 파이썬`for` 문법 : 블럭 코드 vs 싱글 라인 생성자 표현식 (0) | 2018.10.23 |
[PYTHON] 단위 테스트에서 open (file_name) 조롱 (0) | 2018.10.23 |
[PYTHON] Tensorflow r1.0 : 요구 사항을 만족하는 버전을 찾을 수 없습니다. tensorflow (0) | 2018.10.23 |