Flask SqlAlchemy : TypeError: 'Class' object is not iterable

13,540

I fail to understand why such an error appears. What is the right way of adding a mapped object ?

Notice that when you configure you wallet relationship you use lazy="dynamic" option. This way you are setting up a dynamic relationship. As it is designed to be used with large collections it doesn't really makes much sense to use it with one-to-one relationship.

At the same time it alters the way you can assign to your scalar relationship, i.e. you cannot assing your single object directly:

self.wallet = wallet

but you must use an iterable

self.wallet = [wallet]

So you have two solutions here: either assign collection of one element as shown above or better yet stop using dynamic collections for this relationship.

Share:
13,540

Related videos on Youtube

Yace
Author by

Yace

Updated on October 20, 2022

Comments

  • Yace
    Yace over 1 year

    I'm following the Flask-SQLAlchemy tutorial. I have Flask 0.9, sqlalchemy 0.7.8 and flask-sqlalchemy 0.16 on python 2.6. (and I work with eclipse)

    (The tuto is here : http://packages.python.org/Flask-SQLAlchemy/models.html)

    I have 2 classes : a man and a wallet. There is a 1-1 relationship. (Each man has his own wallet)

    class Man(db.Model):
        sid = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(100), unique=False)
        wallet = db.relationship('Wallet', backref='man', lazy='dynamic', uselist=False)
    
        def __init__(self, wallet):
            self.wallet = wallet
    
    class Wallet(db.Model):
        sid = db.Column(db.Integer, primary_key=True)
        account = db.Column(db.Integer)
        manId = db.Column(db.Integer, db.ForeignKey('man.sid'))
    
        def __init__(self, account):
            self.account = account
    

    In my "main" module, I create my database :

    app = Flask(__name__)
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:PATH'
    db = SQLAlchemy(app)
    

    In this very same module, I try to attach a Wallet to a Man :

    if __name__ == "__main__":
        db.create_all() 
        w1 = Wallet(132)
        w2 = Wallet(18)
        db.session.add(w1)
        db.session.add(w2)
        db.session.commit()
        man1 = Man(w1)
        db.session.add(man1)
        db.session.commit()
    

    But I get this error :

    TypeError: 'Wallet' object is not iterable
    

    I fail to understand why such an error appears. What is the right way of adding a mapped object ?

    PS : I've been on the SQLAlchemy tutorial and I believe that they would declare things differently :

    class Man(db.Model):
        sid = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(100), unique=False)
        wallet = db.relationship('Wallet', backref='man', lazy='dynamic', uselist=False)
        manId = db.Column(db.Integer, db.ForeignKey('man.sid'))
        def __init__(self, wallet):
            self.wallet = wallet
    
    class Wallet(db.Model):
        sid = db.Column(db.Integer, primary_key=True)
        account = db.Column(db.Integer)
    
        def __init__(self, account):
            self.account = account
    

    Which tutorial should I trust ?

    Thank you very much !

  • zzzeek
    zzzeek over 11 years
    this is basically the right answer. it's nonsensical to use "uselist=False" with "lazy='dynamic'", and I think the 'dynamic' flag here is going to trump the "uselist". Really it shouldn't be allowed at all, will see if I can add that.
  • zzzeek
    zzzeek over 11 years
    I've updated the docs at docs.sqlalchemy.org/en/rel_0_7/orm/… and there is also a warning in 0.7.9 and an exception raise in 0.8.