由于Query-invoked autoflush导致的SQLAlchemy OperationalError

时间:2016-11-20 01:00:47

标签: python mysql sql sqlalchemy flask-sqlalchemy

我在数据库中有一个表,它通过SQLAlchemy创建和访问:

我使用Flask-SQLAlchemy添加一条记录,如下所示:

...
content = request.form['content']
date = datetime.today()
post = Post(date, content)
db.session.add(post)
db.session.commit()
...

此记录已添加到表格中。在执行该代码之后,我查询另一个表:

userID = session['userID']
posts = db.session.query(Post).filter_by(userID=userID).count()

但是我在查询期间收到错误:

  

OperationalError :(由于Query-invoked autoflush引发;   如果发生此刷新,请考虑使用session.no_autoflush块   过早地)(_ mysql_exceptions.OperationalError)(1292,"不正确   日期值:' 11/20'对于列'日期'在第1行")[SQL:u'更新   帖子SET date =%s WHERE posts.id =%s'] [参数:((' 11/20',   1L))]

为什么在将记录添加到表格时已经指定了帖子的日期?还有什么原因可能是这个错误的原因?感谢。

修改

这就是表模型的样子:

class Post(db.Model):

  __tablename__ = 'posts'

  id = db.Column(db.Integer, primary_key=True)
  content = db.Column(db.String(500))
  date = db.Column(db.Date, nullable=False)

  def __init__(self, id, content, date):
      self.id = id
      self.content = content
      self.date = date

3 个答案:

答案 0 :(得分:2)

Stephane是正确的,您将错误的类型传递给模型,或者传递datetime.date对象或更改模型的定义。至于问题的第一部分,我建议阅读有关sessions and flushing的内容。这很重要:

  

跟踪对会话维护的对象的所有更改 - 在再次查询数据库之前或在提交当前事务之前,它会刷新对数据库的所有挂起更改。

因此,通过创建post对象并将其添加到会话中,您只进行了挂起的更改,但此时尚未与数据库进行通信。使用flush()会发生这种情况,您可以手动或自动调用,例如,通过调用commit()。

(顺便说一句。你不需要为模型创建自己的init方法,请参阅http://docs.sqlalchemy.org/en/latest/orm/tutorial.html#adding-and-updating-objects

答案 1 :(得分:1)

date = datetime.today()返回日期时间对象(日期和时间)

Post模型的日期属性是db.Date(日期没有时间)

尝试:

  from datetime import date

  ...

  content = request.form['content']

  date = date.today()    #inject a Date object rather than a Datetime

或:

  class Post(db.Model):     #modify Post schema

  ...

     date = db.Column(db.TIMESTAMP, nullable=False)

答案 2 :(得分:-1)

此错误可能来自其他查询, 即使您解决了,如果您不回滚上一个会话错误,仍会发生异常

您可以捕获异常和回滚事务

通常在我的烧瓶应用程序中,我在请求结束时提交会话

@app_instance.after_request
def after(response):
    try:
        # commit transaction
        db.session.commit()
    except Exception:
        db.session.rollback()
        raise

    return response