2009-12-14 13 views
4

我試圖在與the example in the docs非常類似的情況下使用關聯代理的標記。這裏是我的架構(這是一個博客)的一個子集,使用聲明:爲什麼SQLAlchemy/associationproxy複製我的標籤?

class Tag(Base): 
    __tablename__ = 'tags' 
    id   = Column(Integer, primary_key=True) 
    tag   = Column(Unicode(255), unique=True, nullable=False) 

class EntryTag(Base): 
    __tablename__ = 'entrytags' 
    entry_id  = Column(Integer, ForeignKey('entries.id'), key='entry', primary_key=True) 
    tag_id  = Column(Integer, ForeignKey('tags.id'), key='tag', primary_key=True) 

class Entry(Base): 
    __tablename__ = 'entries' 
    id   = Column(Integer, primary_key=True) 
    subject  = Column(Unicode(255), nullable=False) 
    # some other fields here 
    _tags   = relation('Tag', backref='entries', secondary=EntryTag.__table__) 
    tags   = association_proxy('_tags','tag') 

以下是我想要使用它:

>>> e = db.query(Entry).first() 
>>> e.tags 
[u'foo'] 
>>> e.tags = [u'foo', u'bar'] # really this is from a comma-separated input 
db.commit() 
Traceback (most recent call last): 
[...] 
sqlalchemy.exc.IntegrityError: (IntegrityError) duplicate key value violates unique constraint "tags_tag_key" 
'INSERT INTO tags (id, tag) VALUES (%(id)s, %(tag)s)' {'tag': 'bar', 'id': 11L} 
>>> map(lambda t:(t.id,t.tag), db.query(Tag).all()) 
[(1, u'foo'), (2, u'bar'), (3, u'baz')] 

ID爲2已經存在的標籤u'bar';爲什麼SQLAlchemy沒有附加那個而不是試圖創建它呢?某種程度上我的模式錯了嗎?

回答

3

聲明:自從我使用SQLAlchemy以來,這已經過時了,所以這比任何事情都更值得猜測。

看起來您期待SQLAlchemy在多對多表上執行插入操作時神奇地取出字符串「bar」並查找相關標籤。我期望這是無效的,因爲有問題的字段('標記')不是主鍵。

想象一下類似的情況,其中你的標籤表實際上是評論,也有一個ID和一個文本字段。您希望能夠使用上面使用的相同的e.comments = ['u'Foo','u'Bar']語法將條目添加到條目中,但您希望它只執行插入,而不是檢查具有相同內容的現有評論。

所以這可能是它在這裏做的事情,但它會觸及標籤名稱的唯一性約束並失敗,假設您嘗試做錯誤的事情。

如何解決?儘管我不知道SQLAlchemy如何有效地處理它,但是使用tags.tag作爲主鍵可以說是正確的做法。如果沒有,請在將它們分配給條目之前,按名稱查詢Tag對象。您可能需要編寫一個帶有unicode字符串的小實用程序函數,並返回現有標籤或爲您創建一個新標籤。

+0

那麼,我鏈接的例子似乎暗示它會起作用。至少,對於他們來說,定義這個不錯的代理將標籤呈現爲字符串列表似乎很愚蠢,只能說我應該在使用它之前手動查找標籤ID。 他們的例子有一個奇怪的地方,它實際上並沒有'Tag.tag'上的唯一約束。也許他們的例子只是以很多重複標籤結束,在這一點上,我可能會拋棄「標籤」對象,並直接在「EntryTag」中標記標籤。但後來我失去了擁有不錯的backref'entries'的能力,對吧? – 2009-12-14 11:01:58

+0

其實你是對的。他們甚至把它放在他們的常見問題解答中:http://www.sqlalchemy.org/trac/wiki/FAQ#Istherewayto自動創建一個獨特的關鍵字或其他關鍵詞,而不需要關鍵詞,並且可以在其中包含關鍵詞及其建議的修正:http://www.sqlalchemy。org/trac/wiki/UsageRecipes/UniqueObject – 2009-12-14 13:28:34

+0

看着它,我同意他們的例子是不明確的,因爲你可能合理地期望相同的關鍵字解析爲相同的實例。如果他們選擇了第二張表格而不是唯一性的建議,會更好。 – Kylotan 2009-12-15 01:11:16

0

我從來沒有使用SQLAlchemy的0.5,但(我用最後的應用程序是基於0.4),但我可以看到你的代碼一個怪癖:你應該修改的association_proxy對象,而不是重新分配它。

嘗試做這樣的事情:

e.tags.append(u"bar") 

而不是

e.tags = ... 

如果還是不行,請嘗試粘貼一個完整的工作示例爲那些表(!(包括進口),請)和我會給你更多的建議。

+0

好想,但是'append'給出了相同的結果(提交時重複鍵)。當我不在工作時,將完成這個例子(這不是一個工作項目)。 – 2009-12-14 10:53:11

相關問題