I am working on building a role based auth system in Flask. I have followed the SQLAlchemy docs in setting up a many to many relationship as a user could have multiple roles and a role multiple users. Here are my models with the associated table:
class Role(db.Model):
__tablename__ = "roles"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(30), unique=True)
users = db.relationship("User", secondary=user_roles, backref="roles")
class User(UserMixin, db.Model):
__tablename__ = "users"
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), index=True, unique=True)
email = db.Column(db.String(120), index=True, unique=True)
password_hash = db.Column(db.String(128))
firstName = db.Column(db.String(64), index=True, unique=False)
lastName = db.Column(db.String(64), index=True, unique=False)
last_login = db.Column(db.DateTime, default=datetime.utcnow)
user_roles = db.Table(
"user_roles",
db.Model.metadata,
db.Column("roles.id", db.ForeignKey("roles.id"), primary_key=True),
db.Column("users.id", db.ForeignKey("users.id"), primary_key=True),
)
I did not include the methods as those don't seem to be causing the issue. I am getting the following Traceback when trying to add a user to the database.
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "<string>", line 4, in __init__
File "/home/ryan/adstrat/adstrat-spec-claims/asc/lib/python3.9/site-packages/sqlalchemy/orm/state.py", line 480, in _initialize_instance
manager.dispatch.init_failure(self, args, kwargs)
File "/home/ryan/adstrat/adstrat-spec-claims/asc/lib/python3.9/site-packages/sqlalchemy/util/langhelpers.py", line 70, in __exit__
compat.raise_(
File "/home/ryan/adstrat/adstrat-spec-claims/asc/lib/python3.9/site-packages/sqlalchemy/util/compat.py", line 207, in raise_
raise exception
File "/home/ryan/adstrat/adstrat-spec-claims/asc/lib/python3.9/site-packages/sqlalchemy/orm/state.py", line 477, in _initialize_instance
return manager.original_init(*mixed[1:], **kwargs)
File "/home/ryan/adstrat/adstrat-spec-claims/asc/lib/python3.9/site-packages/sqlalchemy/orm/decl_base.py", line 1157, in _declarative_constructor
setattr(self, k, kwargs[k])
File "/home/ryan/adstrat/adstrat-spec-claims/asc/lib/python3.9/site-packages/sqlalchemy/orm/attributes.py", line 459, in __set__
self.impl.set(
File "/home/ryan/adstrat/adstrat-spec-claims/asc/lib/python3.9/site-packages/sqlalchemy/orm/attributes.py", line 1602, in set
collections.bulk_replace(
File "/home/ryan/adstrat/adstrat-spec-claims/asc/lib/python3.9/site-packages/sqlalchemy/orm/collections.py", line 843, in bulk_replace
appender(member, _sa_initiator=initiator)
File "/home/ryan/adstrat/adstrat-spec-claims/asc/lib/python3.9/site-packages/sqlalchemy/orm/collections.py", line 1169, in append
item = __set(self, item, _sa_initiator)
File "/home/ryan/adstrat/adstrat-spec-claims/asc/lib/python3.9/site-packages/sqlalchemy/orm/collections.py", line 1134, in __set
item = executor.fire_append_event(item, _sa_initiator)
File "/home/ryan/adstrat/adstrat-spec-claims/asc/lib/python3.9/site-packages/sqlalchemy/orm/collections.py", line 753, in fire_append_event
return self.attr.fire_append_event(
File "/home/ryan/adstrat/adstrat-spec-claims/asc/lib/python3.9/site-packages/sqlalchemy/orm/attributes.py", line 1429, in fire_append_event
value = fn(state, value, initiator or self._append_token)
File "/home/ryan/adstrat/adstrat-spec-claims/asc/lib/python3.9/site-packages/sqlalchemy/orm/attributes.py", line 1765, in emit_backref_from_collection_append_event
child_state, child_dict = instance_state(child), instance_dict(child)
AttributeError: 'str' object has no attribute '_sa_instance_state'
I have read through numerous questions about this but many are dealing with querying the database or failing on the commit step. I am failing on the db.session.add step. I have an empty database and this would be my first user so there should be no issues with unique tests failing.
Here's an example of what I am trying to do in the shell
u = User(username='Ryan', email='ryan@test.com', firstName='Ryan', lastName='Findley', roles=['Admin'])
Any thoughts?