Sto cercando di implementare una relazione molti-a-molti autoreferenziale usando dichiarative su SQLAlchemy.Come posso ottenere una relazione molti-a-molti autoreferenziale sull'ORM di SQLAlchemy che fa riferimento allo stesso attributo?
La relazione rappresenta l'amicizia tra due utenti. Ho scoperto online (sia nella documentazione che su Google) come creare una relazione m2m autoreferenziale in cui, in qualche modo, i ruoli sono differenziati. Ciò significa che in queste relazioni m2m UserA è, ad esempio, il capo di UserB, quindi lo elenca sotto un attributo 'subordinati' o cosa hai. Allo stesso modo UtenteB elenca UtenteA sotto 'superiori'.
Questo costituisce un problema, perché siamo in grado di dichiarare un backref allo stesso tavolo in questo modo:
subordinates = relationship('User', backref='superiors')
Quindi c'è, ovviamente, l'attributo 'superiori' non è esplicito all'interno della classe.
In ogni caso, ecco il mio problema: cosa succede se voglio tornare allo stesso attributo dove sto chiamando il backref? Come questo:
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=??????
)
Questo ha senso, perché se una amicizia con B i ruoli di relazione sono gli stessi, e se invoco gli amici di B dovrei ottenere una lista con A in esso. Questo è il codice problematico in piena:
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
)
Scusate se questo è troppo testo, voglio solo essere il più esplicito che posso con questo. Non riesco a trovare alcun materiale di riferimento a questo sul web.
Questo sembra essere un po 'soggetto a errori: si può accidentalmente accodare a 'all_friends' e non sarà possibile ottenere alcun preavviso. Eventuali suggerimenti? – Halst
Anche questo consente di duplicare le amicizie con ID scambiati (come '1, 2' e' 2, 1'). Puoi mettere un vincolo che un ID sia maggiore di un altro, ma poi devi tenere traccia di quali utenti possono essere aggiunti a quale attributo 'amici' degli utenti. – Halst
viewonly = True non ha alcuna influenza sul comportamento della raccolta in Python. Se sei veramente preoccupato per gli allegati a questa raccolta, puoi utilizzare collection_cls e applicare un elenco o un tipo di set con metodi di mutazione sovrascritti per lanciare NotImplementedError o simili. – zzzeek