2013-08-25 31 views
1

我完全用flask和sqlalchemy創建新的。我試圖製作一個網站,以便更好地理解燒瓶。我有類似博客的地方,用戶可以創建帖子並設置多個標籤。我用flask-sqlalchemy和wtforms-alchemy。我有2種型號無法更新Flask中的多對多關係條目

association_table = db.Table('association', 
    db.Column('post_id', db.Integer, db.ForeignKey('post.id')), 
    db.Column('category_id', db.Integer, db.ForeignKey('category.id')) 
) 

class Post(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    title = db.Column(db.String(80), nullable=False) 
    body = db.Column(db.Text, nullable=False) 
    pub_date = db.Column(db.DateTime) 

    categories = db.relationship('Category', secondary=association_table, 
          backref=db.backref('posts', lazy='dynamic')) 

    ... 
class Category(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    name = db.Column(db.String(50)) 
    ... 

我可以創建新的崗位與下一個視圖

def add(): 
    form = PostForm(request.form) 
    if request.method == 'POST' and form.validate(): 
     post = Post(form.title.data, form.body.data) 
     db.session.add(post) 
     tags = form.tags.data.split(',') 
     for tag in tags: 
      category = Category.query.filter_by(name=tag.strip()).first() 
      if not category: 
       category = Category(tag.strip()) 
      post.categories.append(category) 
     db.session.commit() 
     return redirect(...) 
    return render_template(...) 

這工作,因爲它應該。但是我在編輯帖子時遇到了一些問題。當我改變標題或正文時,我必須使用db.session.merge(post),否則它不想保存數據庫中的更改。但在所有教程中都沒有合併方法。 第二個問題是我無法更新帖子的標籤。我可以創建一個新標籤並將其添加到某個帖子。但是,如果我嘗試將現有標籤添加到任何帖子,我有一個錯誤。

AssertionError: A conflicting state is already present in the identity map for key (<class 'db.models.Category'>, (1,)) 

我的觀點看起來像

def edit(post_id): 
    post = Post.query.get(post_id) 
    form = PostForm(request.form, post) 
    if request.method == 'POST' and form.validate(): 

     ... 

     tags = form.tags.data.split(',') 
     for tag in tags: 
      category = Category.query.filter_by(name=tag.strip()).first() 
      if not category: 
       category = Category(tag.strip()) 
      db.session.remove() 
      post.categories.append(category) 
     form.populate_obj(post) 
     db.session.merge(post) 
     db.session.commit() 
     return redirect(...) 
    else: 
     ... 

    return render_template(...) 

另外,如果我不使用db.session.remove()我會得到另一個錯誤

InvalidRequestError: Object '<Category at 0x7f9de40c0d90>' is already attached to session '6' (this is '1') 

我在哪裏錯了?謝謝你的幫助!

一個更新。只是爲了測試。如果我從一篇文章迭代標籤列表,我可以刪除這些標籤並將其附加回來。

tags = list(post.categories) 
for tag in tags: 
    post.categories.remove(tag) 

for tag in tags: 
    post.categories.append(tag)  

但如果我刪除標籤,然後從數據庫中獲取標記,並嘗試添加 - 得到一個錯誤

tags = list(post.categories) 
for tag in tags: 
    post.categories.remove(tag) 

for tag in tags: 
    category = Category.query.filter_by(name=tag.name).first() 
    post.categories.append(tag) 


AssertionError: A conflicting state is already present in the identity map for key (<class 'db.models.Category'>, (1,)) 

我很困惑

回答

1

我發現這個問題。我使用WooshAlchemy進行文本搜索。它會創建不同的會話。關於這個的大文章可以發現here

+0

是的,這是使用flask_whooshalchemy庫時的一個問題。 Miguel Grinberg的補丁(上面答案中的鏈接)最終被合併到庫的github存儲庫中。但截至2014年5月尚未發佈。如果您需要通過此錯誤,您需要手動將修補程序應用於flask_whooshalchemy.py。 – Will

3

爲什麼

db.session.remove() 

您碼?拇指與sqlalchemy

快速規則:

只有當你創建一個新的實例,你必須將它添加到會話中。 查詢返回的所有內容(對於關係也是有效的)已經在會話中,因此您不需要添加或刪除任何內容。

所以要添加一個新的類別,你只需

  • 創建對象
  • 添加到會話
  • 追加到categories列表
  • db.session.commit

要修改類別

  • 修改所需categories條目
  • db.session.commit

要刪除關聯

  • categories列表中刪除
  • db.session.commit

要刪除一個類別對象您還需要

  • db.session.delete(cat)
+0

感謝您的回覆。正如我沒有db.session.remove()所述,我有另一個錯誤InvalidRequestError。我可以創建新帖子,新類別,編輯帖子的其他字段,但不能將現有類別附加到任何現有帖子。我猜這個問題在代碼更深的地方,不僅在我發佈的部分 – poul