Flask-SQLAlchemy InvalidRequestError: объект уже прикреплен к сеансу

Я создаю проект форума с помощью Flask и управляю всеми пользователями, потоками, сообщениями и т. д. с помощью Flask-SQLAlchemy. Однако я обнаружил, что когда я пытаюсь сделать x (например, отредактировать сообщение), я получаю InvalidRequestError, если пытаюсь сделать что-то еще (например, удалить сообщение).

Для редактирования поста

def post_edit(id, t_id, p_id):
  post = Post.query.filter_by(id=p_id).first()
  if post.author.username == g.user.username:
    form = PostForm(body=post.body)
    if form.validate_on_submit():
      post.body = form.body.data
      db.session.commit()
      return redirect(url_for('thread', id=id, t_id=t_id))
    return render_template('post_edit.html', form=form, title='Edit')
  else:
    flash('Access denied.')
    return redirect(url_for('thread', id=id, t_id=t_id))

и удаление поста,

@app.route('/forum=<id>/thr=<t_id>/p=<p_id>/delete', methods=['GET','POST'])
def post_delete(id, t_id, p_id):
  post = Post.query.filter_by(id=p_id).first()
  if post.author.username == g.user.username:
    db.session.delete(post)
    db.session.commit()
    return redirect(url_for('thread', id=id, t_id=t_id))
  else:
    flash('Access denied.')
    return redirect(url_for('thread', id=id, t_id=t_id))

и публикую пост

@app.route('/forum/id=<id>/thr=<t_id>', methods=['GET','POST'])
def thread(id, t_id):
  forum = Forum.query.filter_by(id=id).first()
  thread = Thread.query.filter_by(id=t_id).first()
  posts = Post.query.filter_by(thread=thread).all()
  form = PostForm()
  if form.validate_on_submit():
    post = Post(body=form.body.data,
                timestamp=datetime.utcnow(),
                thread=thread,
                author=g.user)
    db.session.add(post)
    db.session.commit()
    return redirect(url_for('thread', id=id, t_id=t_id))
  return render_template('thread.html', forum=forum, thread=thread, posts=posts, form=form, title=thread.title)

К сожалению, единственный верный способ решить эту проблему — сбросить скрипт, который фактически запускает приложение, run.py.

#!bin/python

from app import app
app.run(debug=True,host='0.0.0.0')

person Ganye    schedule 13.05.2013    source источник


Ответы (2)


Вы используете WooshAlchemy, потому что это может быть частью вашей проблемы. Описано здесь

Он описывает «исправление», которое требует модификации расширения WooshAlchemy.

Обычно это может означать, что вы вызвали объект модели Post, а затем присоединили его с помощью «session.add», а затем попытались «session.delete» или сделали другой «session.add» для того же объекта.

Кроме того, ваша маршрутизация запросов немного странная для flask. Я никогда раньше не видел нотации типа «thr=‹t_id›» с Flask. Это хорошо сработало для вас?

http://flask.pocoo.org/docs/quickstart/#variable-rules

person Dexter    schedule 13.05.2013
comment
Похоже, WhooshAlchemy действительно была проблемой. Что касается обозначения, это просто сокращение от thr=‹thread_id›. - person Ganye; 14.05.2013
comment
Я имел в виду часть thr=. Но я думаю, вы могли бы сделать /thr=44/p=32/c=21 формат URL-адреса, я просто нашел это странным, вот и все. Хотя я рад, что мы разобрались с проблемой. - person Dexter; 14.05.2013
comment
Это именно то, что есть; так, например, конкретная ветка (8) на форуме (1) создает URL-адрес /forum/id=1/thr=8. - person Ganye; 15.05.2013

Я думаю, что ваш пост редактирования сделан неправильно. Используйте функцию populate_obj.

@app.route('/forum=<id>/thr=<t_id>/p=<p_id>/edit', methods=['GET','POST'])
def post_edit(id, t_id, p_id):
    post = Post.query.filter_by(id=p_id).first()
    if post.author.username == g.user.username:
        form = PostForm(obj=post)
        if form.validate_on_submit():
            form.populate_obj(post)
            db.session.commit()
            return redirect(url_for('thread', id=id, t_id=t_id))
        return render_template('post_edit.html', form=form, title='Edit')
   else:
       flash('Access denied.')
       return redirect(url_for('thread', id=id, t_id=t_id))
person codegeek    schedule 13.05.2013