Почему появляется ошибка relationship expects a class or a mapper argument в SQLAlchemy?

Создал таблицы для базы данных с помощью sqlalchemy.

class Base(DeclarativeBase):
    pass


class UserPlaylistLink(Base):
    __tablename__ = "user_playlist_link"
    user_id: Mapped[UUID] = mapped_column(ForeignKey("user.id"), primary_key=True)
    playlist_id: Mapped[UUID] = mapped_column(ForeignKey("playlist.id"), primary_key=True)
    status: Mapped[PlaylistStatus] = mapped_column(Enum(PlaylistStatus), nullable=False)


class User(Base):
    __tablename__ = "user"
    id: Mapped[UUID] = mapped_column(primary_key=True)
    mail: Mapped[str]
    playlists: Mapped[list["Playlist"]] = relationship("playlist", secondary="UserPlaylistLink", back_populates="users")


class Playlist(Base):
    __tablename__ = "playlist"
    id: Mapped[UUID] = mapped_column(primary_key=True)
    name: Mapped[str]
    author_id: Mapped[UUID] = mapped_column(nullable=False)
    users: Mapped[list["User"]] = relationship("user", secondary="UserPlaylistLink", back_populates="playlists")

Но когда пытался протестировать добавление пользователя в базу стала появляться ошибка:

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <Relationship at 0x1271ff24eb0; placelists>
_RelationshipProperty__argument = None

    @util.preload_module("sqlalchemy.orm.mapper")
    def _setup_entity(self, __argument: Any = None) -> None:
        if "entity" in self.__dict__:
            return
    
        mapperlib = util.preloaded.orm_mapper
    
        if __argument:
            argument = __argument
        else:
            argument = self.argument
    
        resolved_argument: _ExternalEntityType[Any]
    
        if isinstance(argument, str):
            # we might want to cleanup clsregistry API to make this
            # more straightforward
            resolved_argument = cast(
                "_ExternalEntityType[Any]",
                self._clsregistry_resolve_name(argument)(),
            )
        elif callable(argument) and not isinstance(
            argument, (type, mapperlib.Mapper)
        ):
            resolved_argument = argument()
        else:
            resolved_argument = argument
    
        entity: _InternalEntityType[Any]
    
        if isinstance(resolved_argument, type):
            entity = class_mapper(resolved_argument, configure=False)
        else:
            try:
                entity = inspect(resolved_argument)
            except sa_exc.NoInspectionAvailable:
                entity = None  # type: ignore
    
            if not hasattr(entity, "mapper"):
>               raise sa_exc.ArgumentError(
                    "relationship '%s' expects "
                    "a class or a mapper argument (received: %s)"
                    % (self.key, type(resolved_argument))
                )
E               sqlalchemy.exc.ArgumentError: relationship 'playlists' expects a class or a mapper argument (received: <class 'sqlalchemy.sql.schema.Table'>)

Можете подсказать, в чем проблема? Может я как-то неправильно понял как работает relationship?

Если заменить строку в relationship(secondary=...) на сам класс, вместо строки, то появляется предупреждение в IDE: Expected type 'FromClause | str | () -> FromClause | None', got 'Type[UserPlaylistLink]' instead.


Ответы (1 шт):

Автор решения: Maksim Alekseev

В строке ниже, передано название таблицы "playlist"

playlists: Mapped[list["Playlist"]] = relationship("playlist", secondary="UserPlaylistLink", back_populates="users")

нужно передать название класса "Playlist"

playlists: Mapped[list["Playlist"]] = relationship("Playlist", secondary="UserPlaylistLink", back_populates="users")
→ Ссылка