27
votes

I have 3 models created with Flask-SQLalchemy: User, Role, UserRole

role.py:

class Role( ActiveRecord, db.Model ):

    __tablename__ = "roles"

    #   Schema
    id = db.Column( db.Integer, primary_key = True )
    name = db.Column( db.String( 24 ), unique = True )
    description = db.Column( db.String( 90 ) )

    users = db.relationship( "User", secondary = "UserRole", \
        backref = db.backref( "roles" ) )

user.py:

class User( db.Model, ActiveRecord ):

    __tablename__ = "users"

    #   Schema
    id = db.Column( db.Integer, primary_key = True )
    email = db.Column( db.String( 90 ), unique = True )
    password = db.Column( db.String( 64 ) )

    #   Relations
    roles = db.relationship( "Role", secondary = "UserRole", \
        backref = db.backref( "users" ) )

user_role.py:

class UserRole( ActiveRecord, db.Model ):

    __tablename__ = "user_roles"

    #   Schema
    user_id = db.Column( db.Integer, db.ForeignKey( 'users.id' ), primary_key = True )
    role_id = db.Column( db.Integer, db.ForeignKey( 'roles.id' ), primary_key = True )

If I try (in the console) to get all users via User.query.all() I get AttributeError: 'NoneType' object has no attribute 'all' and if I try again I get another error saying:

sqlalchemy.exc.InvalidRequestError: One or more mappers failed to initialize - can't proceed with initialization of other mappers.  Original exception was: type object 'UserRole' has no attribute 'foreign_keys'

Can anyone shed a light on what is it exactly that I'm doing wrong? I think I had this code running ok a few months ago, but I updated SQLAlchemy, Flask and Flask-SQLAlchemy recently and it stopped. It's just a side project.

1
Part of the reason to post source code is so that we can attempt to reproduce the problem on our side. However, without us knowing what ActiveRecord is, or how you've set up the "console" that you try to run the command in, we cannot do that. Is there a way you could create a single script that duplicates the problem?Mark Hildreth

1 Answers

55
votes

it's a little tough here because you are using some unknown base classes like "ActiveRecord" and such. However, it looks pretty much like that "secondary" argument is wrong:

class User( db.Model, ActiveRecord ):

    __tablename__ = "users"

    #   Schema
    id = db.Column( db.Integer, primary_key = True )
    email = db.Column( db.String( 90 ), unique = True )
    password = db.Column( db.String( 64 ) )

    #   Relations
    roles = db.relationship( "Role", secondary = "UserRole", \
        backref = db.backref( "users" ) )

secondary needs to refer to a Table object, not a mapped class, if by string name then it would be "user_roles":

    roles = db.relationship( "Role", secondary = "user_roles", \
        backref = db.backref( "users" ) )