I have 2 Tables in SQLAlchemy (using declerative_base()) that are joined via a seperate Table relationship
# no comment on the wired naming....
site_word = Table('word_site', Base.metadata,
Column('site_id', Integer, ForeignKey('sites.site_id'), nullable = False, primary_key = True),
Column('word_id', Integer, ForeignKey('site_words.word_id'), nullable = False, primary_key = True))
Word mapping
class Word(Base):
# snip
word = Column('word', Text, nullable = False, unique = True)
sites = relationship('Site', secondary = site_word, back_populates = 'words')
Site mapping
class Site(Base):
# snip
words = relationship('Word', secondary = site_word, back_populates = 'sites')
Inserting works like expected, inserting of already existing words fails of course due to unique in Word.word.
I tried using a before_insert event to check if the item already exists.
event.listen(Word, 'before_insert', some_event)
I can get the information to identify the word uniquly as expected but I don’t know how to add a new value to the join table (site_word).
I could write a trigger or procedure for the database but don’t want to move too much logic into the database (don’t know if this would be possible since the Site wouldn’t be known at that time). I could remove the constraint for the word-column but I still can’t figure out how to access the information (the other end of the join) to create an entry in the join table, but not in the Word table.
I am looking for a way to create a entry in the site_word and Site table only.
update 1:
I could attach the event to the Site but I don’t see a possibility to get the information of the to-be-inserted Site. Is there a possibility to save the Site and create the join-relation afterwards?
I managed to do it. Mark Gemmill’s answer got me thinking in the right direction.
I need to listen to an AttributeEvent instead of an MapperEvent.
Then I can do something like:
This either returns the existing word from the table or simply returns the mapped object that needs to be persisted.