Background: Flask / Flask-SQLAlchemy / Flask-WTF, using declarative and scoped session
Simple POST
operation:
@tas.route(\'/order_add\
I had a similar problem with QuerySelectField:
forms.py :
class SurgeryForm(Form):
study = QuerySelectField('Study',
query_factory=StudyGroup.query.all,
get_label='name')
models.py
class Animal(db.Model):
study_id = db.Column(db.Integer, db.ForeignKey('study_group.id'))
class StudyGroup(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50))
animals = db.relationship('Animal', backref='group', lazy='dynamic')
views.py:
def do_surgery():
form = SurgeryForm(request.form)
if form.validate_on_submit():
a = models.Animal()
form.populate_obj(a) # Gather the easy stuff automagically
#a.group = form.data['study'] #FAILS!
a.study_id = form.data['study'].id #WORKS!
It seems that SQLAlchemy (or possibly Flask-SQLAlchemy or Flask-WTF) uses one session to gather the values in the QuerySelectField and another session to create the new Animal object.
If you try to attach the StudyGroup object to the Animal using the backref (Animal.group) you'll run into this problem (since the objects associated with different sessions). The workaround that I'm using is to set the foreign key (Animal.study_id) directly.
Clearly I'm a little late to the party with this answer, but I hope it helps someone!
seems a problem with session mix up, I used it as follows and it works:
from <project> import db
from <project.models import Category
category = QuerySelectField('category', query_factory=lambda: db.session.query(Category), get_pk=lambda a: a.id, get_label=lambda a: a.name)
That's weird. Why are you creating the engine and declarative base explicitly if you're using flask-sqlalchemy? That's likely where your problem is. It looks like you have two engines and sessions running concurrently, that's why you got the error.
Instead of creating the engine explicitly, you should use just:
from flask.ext.sqlalchemy import SQLAlchemy
db = SQLAlchemy()
And inside your app factory:
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///fundmanager_devel.db'
db.init_app(app)
Then your base declarative model is db.Model
, your session is in db.session
, and you should let flask request context manage session creation.
Check the minimal application example in Flask-SQLAlchemy docs:
http://pythonhosted.org/Flask-SQLAlchemy/quickstart.html#a-minimal-application
This is how it's recommended by SQLAlchemy:
Most web frameworks include infrastructure to establish a single Session, associated with the request, which is correctly constructed and torn down corresponding torn down at the end of a request. Such infrastructure pieces include products such as Flask-SQLAlchemy, for usage in conjunction with the Flask web framework, and Zope-SQLAlchemy, for usage in conjunction with the Pyramid and Zope frameworks. SQLAlchemy strongly recommends that these products be used as available.
http://docs.sqlalchemy.org/en/rel_0_9/orm/session.html