2011-08-17 53 views
1

我有2個表中的SQLAlchemy(使用declerative_base()),它們通過一個單獨的表的關係陣營上UniqueKeyViolation在SQLAlchemy的

# 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)) 

字映射

class Word(Base): 
    # snip 
    word = Column('word', Text, nullable = False, unique = True) 
    sites = relationship('Site', secondary = site_word, back_populates = 'words') 

網站映射

class Site(Base): 
    # snip 
    words = relationship('Word', secondary = site_word, back_populates = 'sites') 
接合

插入如預期的作品,插入已存在的單詞失敗o f當然由於uniqueWord.word

我嘗試使用before_insert事件來檢查項目是否已經存在。

event.listen(Word, 'before_insert', some_event) 

我可以得到的信息爲預期的,但我不知道如何將新值添加到連接表(site_word),以uniquly辨別單詞。

我可以爲數據庫編寫觸發器或過程,但不想將太多邏輯移入數據庫(不知道這是否可能,因爲此時不會知道Site)。我可以刪除word列的約束條件,但我仍然無法弄清楚如何訪問信息(聯接的另一端)在聯接表中創建條目,但不在Word表中。

我正在尋找一種方法在site_word和表中創建一個條目只有

更新1:
我可以在事件附加到Site,但我看不出有可能獲得待插入網站的信息。是否有可能保存網站並在之後創建連接關係?

回答

1

我設法做到了。 Mark Gemmill的answer讓我思考着正確的方向。

我需要聽取AttributeEvent而不是MapperEvent。

event.listen(Site.words, 'append', test_event, retval = True) 

然後,我可以這樣做:

def test_event(target, value, initiator): 
    try: 
     return session.query(Word).filter(Word.word == value.word.lower()).one() 
    except sqlalchemy.orm.exc.NoResultFound: 
     return value 

這要麼返回從表中存在的單詞或只返回被映射的對象,需要保留。

1

如果沒有關於如何處理對象的示例,很難發現問題。我想你正在嘗試做這樣的事情:

site = Site() 
site.words.append(Word('Someword')) 
session.add(site) 
session.commit() 

這當然會引發IntegrityError如果「someword」已經存在。爲了解決這個問題,你需要將它添加到網站之前先查詢詞的數據庫:

def get_unique_word(session, word): 
    try: 
     return session.query(Word).filter(Word.word==word).one() 
    except sqlalchemy.orm.exc.NoResultFound: 
     return Word(word) 

site = Site() 
site.words.append(get_unique_word(session, 'someword')) 
session.add(site) 
session.commit() 

如果這是完全關閉基地,那麼你就必須要更加詳細地描述你的問題。

+0

你的建議不是答案,而是讓我走向解決問題的正確方向。謝謝你的努力。不知道爲什麼我忽略了API中的其他事件;) – DrColossos