sqlalchemy many to many field with extra fields not getting updated

Advertisements

I have two table user and film. These table have many to many relationship with extra field role. I am trying to update role if user and film matched. But this giving me error

user_film_table = Table(
  "user_film_association",
  Base.metadata,
  Column("id", Integer, primary_key=True, index=True),
  Column("user_id", ForeignKey("users.id"), index=True),
  Column("film_id", ForeignKey("film.id"), index=True),
  Column('role', ENUM(UserRoleEnum))  # Role can be 'writer', 'producer', or 'director' 
)
def update_user_role(self, user_id, film_id, new_role):
        user = self.db.query(User).filter(User.id == user_id).first()
        if not user:
            return HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User not found")

        film = self.db.query(Film).filter(Film.id == film_id).first()
        if not film:          
            return HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Film not found")

        if film not in user.film:
            return HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User is not associated with the specified film")

        user_film = self.db.query(user_film_table).filter(user_film_table.c.user_id == user_id, user_film_table.c.film_id == film_id).first()
        print(user_film[0])
        user_film[3].role = new_role.value   #facing error while updating the role
        self.db.add(user_film)
        self.db.commit()
        return {"message": f"User role in film updated to {new_role} successfully", 'status_code': status.HTTP_202_ACCEPTED}

Not able to update the role in many to many field
getting error

raise exc.UnmappedInstanceError(instance) from err
sqlalchemy.orm.exc.UnmappedInstanceError: Class 'sqlalchemy.engine.row.Row' is not mapped

>Solution :

The error you are encountering is because the user_film object you are trying to add using self.db.add(user_film) is not a mapped instance, but rather a row result.

In SQLAlchemy, only “mapped” instances (instances of classes that have been mapped to database tables) can be added to a session for ORM-style CRUD operations.

you can use the update statement provided by SQLAlchemy, which can be used to update specific fields in a row. The where method is used to specify which row(s) should be updated, and the values method is used to specify the new values for the fields.
Here’s how you can fix this:

from sqlalchemy import update

def update_user_role(self, user_id, film_id, new_role):
    user = self.db.query(User).filter(User.id == user_id).first()
    if not user:
        return HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User not found")

    film = self.db.query(Film).filter(Film.id == film_id).first()
    if not film:          
        return HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Film not found")

    if film not in user.film:
        return HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User is not associated with the specified film")

    # Use the update statement
    stmt = (
        update(user_film_table).
        where(user_film_table.c.user_id == user_id, user_film_table.c.film_id == film_id).
        values(role = new_role.value)
    )
    self.db.execute(stmt)
    self.db.commit()
    return {"message": f"User role in film updated to {new_role} successfully", 'status_code': status.HTTP_202_ACCEPTED}

Leave a ReplyCancel reply