0

In models, have a User that can have many roles and Role that can have many users (many-to-many):

class UsersRoles(SQLModel, table=True):
    user_id: int = Field(foreign_key='users.id', primary_key=True)
    role_id: int = Field(foreign_key='roles.id', primary_key=True)


class User(SQLModel, table=True):
    id: int = Field(default=None, primary_key=True)
    name: str
    email: str = Field(unique=True, index=True)
    roles: list['Role'] = Relationship(back_populates='users', link_model=UsersRoles)


class Role(SQLModel, table=True):
    id: int = Field(default=None, primary_key=True)
    name: str = Field(unique=True)
    users: list['User'] = Relationship(back_populates='roles', link_model=UsersRoles)

In the api, declare the endpoint:

@router.post('/user')
def create_user(user: User) -> User:
    with get_session() as session:
        session.add(user)
        session.commit()
        session.refresh(user)
        return user

Then I want to create the User with roles and call the endpoint:

role = Role(name='admin')
user = User(name='Jane', email='test@xyz.com', roles=[role])

# payload = {
#   'name': 'Jane',
#   'email': 'test@xyz.com',
#   'roles': ['admin']
# }
payload = user.json()
response = requests.post('http://localhost:8000/user', json=payload)

Error: Get what looks like a SqlAlchemy error:

state = <sqlalchemy.orm.state.InstanceState object at 0x0000016B1F3B6BF0>
child = {'name': 'user'}
initiator = <sqlalchemy.orm.attributes.AttributeEvent object at 0x0000016B1F2FF780>

    def emit_backref_from_collection_append_event(state, child, initiator):
        if child is None:
            return
    
>       child_state, child_dict = instance_state(child), instance_dict(child)
E       AttributeError: 'dict' object has no attribute '_sa_instance_state'

How can I make this work?

  • The same thing happens whether the role already exists in the DB or not.
  • Works if the payload (user) doesn't have roles in it.
  • The error comes up before the controller code gets executed, ie, in api doesn't even reach the first line inside create_user(...).
Joao Coelho
  • 2,838
  • 4
  • 30
  • 36

0 Answers0