Open
Description
Problem Description
The typehint of
db.relationship("...", secondary=..., back_populates="...")
should be sq_orm.Relationship[...]
, not sq_orm.RelationshipProperty[...]
.
The mismatch of the typehint causes the manual annotation supported by sqlalchemy
fails:

How to fix it
Go here:
flask-sqlalchemy/src/flask_sqlalchemy/extension.py
Lines 953 to 963 in 42a36a3
Make this modification:
def relationship(
self, *args: t.Any, **kwargs: t.Any
- ) -> sa_orm.RelationshipProperty[t.Any]:
+ ) -> sa_orm.Relationship[t.Any]:
"""A :func:`sqlalchemy.orm.relationship` that applies this extension's
Things will get corrected.
It is also recommended to modify this place:
flask-sqlalchemy/src/flask_sqlalchemy/extension.py
Lines 977 to 979 in 42a36a3
But the following place should NOT be changed, because it is consistent with sq_orm
:
flask-sqlalchemy/src/flask_sqlalchemy/extension.py
Lines 965 to 967 in 42a36a3
Codes with typehint errors when using flask-sqlalchemy
# -*- coding: UTF-8 -*-
try:
from typing import List
except ImportError:
from builtins import list as List
from flask_sqlalchemy import SQLAlchemy
import sqlalchemy as sa
from sqlalchemy.orm import Mapped, mapped_column
from sqlalchemy.orm import DeclarativeBase, MappedAsDataclass
class Base(DeclarativeBase, MappedAsDataclass):
"""The base class for creating SQLAlchemy models.
All mixins are defined in the mro list.
All metadata of are defined as attributes.
"""
db = SQLAlchemy(model_class=Base)
roles = db.Table(
"role_users",
sa.Column("user_id", sa.ForeignKey("user.id"), primary_key=True),
sa.Column("role_id", sa.ForeignKey("role.id"), primary_key=True),
)
class User(db.Model):
id: Mapped[int] = mapped_column(primary_key=True, init=False)
# Expression of type "RelationshipProperty[Any]" cannot be assigned to declared type "Mapped[List[Role]]"
# "RelationshipProperty[Any]" is incompatible with "Mapped[List[Role]]"Pylance[reportAssignmentType]
# (https://github.com/microsoft/pyright/blob/main/docs/configuration.md#reportAssignmentType)
roles: Mapped[List["Role"]] = db.relationship(
"Role", secondary=roles, back_populates="users", default_factory=list
)
class Role(db.Model):
id: Mapped[int] = mapped_column(primary_key=True, init=False)
# Expression of type "RelationshipProperty[Any]" cannot be assigned to declared type "Mapped[List[User]]"
# "RelationshipProperty[Any]" is incompatible with "Mapped[List[User]]"Pylance[reportAssignmentType]
# (https://github.com/microsoft/pyright/blob/main/docs/configuration.md#reportAssignmentType)
users: Mapped[List["User"]] = db.relationship(
"User", secondary=roles, back_populates="roles", default_factory=list
)
Codes working perfectly if only using sqlalchemy
# -*- coding: UTF-8 -*-
try:
from typing import List
except ImportError:
from builtins import list as List
import sqlalchemy as sa
from sqlalchemy.orm import Mapped, mapped_column, relationship
from sqlalchemy.orm import DeclarativeBase, MappedAsDataclass
class Base(DeclarativeBase, MappedAsDataclass):
"""The base class for creating SQLAlchemy models.
All mixins are defined in the mro list.
All metadata of are defined as attributes.
"""
roles = sa.Table(
"role_users",
Base.metadata,
sa.Column("user_id", sa.ForeignKey("user.id"), primary_key=True),
sa.Column("role_id", sa.ForeignKey("role.id"), primary_key=True),
)
class User(Base):
__tablename__ = "users"
id: Mapped[int] = mapped_column(primary_key=True, init=False)
roles: Mapped[List["Role"]] = relationship(
"Role", secondary=roles, back_populates="users", default_factory=list
)
class Role(Base):
__tablename__ = "roles"
id: Mapped[int] = mapped_column(primary_key=True, init=False)
users: Mapped[List["User"]] = relationship(
"User", secondary=roles, back_populates="roles", default_factory=list
)
Environment:
- Python version:
3.10.13
- Flask-SQLAlchemy version:
3.1.1
- SQLAlchemy version:
2.0.28
Metadata
Metadata
Assignees
Labels
No labels