エラー全文
sqlalchemy.exc.InvalidRequestError: One or more mappers failed to initialize - can't proceed with initialization of other mappers. Triggering mapper: 'Mapper[ProjectUser(projects_users)]'. Original exception was: When initializing mapper Mapper[ProjectUser(projects_users)], expression 'User' failed to locate a name ('User'). If this is a class name, consider adding this relationship() to the class after both dependent classes have been defined.
多対多モデルの定義
はじめ、下記のようにモデルを設定していました。
from sqlalchemy import Column, String
from sqlalchemy.orm import relationship
from app.db.base_class import Base
from app.models.project_user import ProjectUser
class User(Base):
__tablename__ = "users"
name = Column(String(255), nullable=False)
projects = relationship(
"Project",
secondary=ProjectUser.__tablename__,
back_populates="users",
)
project_user = relationship("ProjectUser")
from sqlalchemy import Column, String
from sqlalchemy.orm import relationship
from app.db.base_class import Base
from app.models.project_user import ProjectUser
class Project(Base):
__tablename__ = "projects"
title = Column(String(255), default="", nullable=False)
users = relationship(
"User",
secondary=ProjectUser.__tablename__,
back_populates="projects",
)
project_user = relationship("ProjectUser")
from sqlalchemy import Column, ForeignKey, Integer
from sqlalchemy.orm import relationship
from app.db.base_class import Base
class ProjectUser(Base):
__tablename__ = "projects_users"
project_id = Column(
Integer, ForeignKey("projects.id", ondelete="RESTRICT"), nullable=False
)
user_id = Column(
Integer, ForeignKey("users.id", ondelete="RESTRICT"), nullable=False
)
user = relationship("User")
project = relationship("Project")
原因
エラー文を読み込むと、「User
という文字列に該当するモデルクラスが見つからない」と言われていることがわかる。
SQLAlchemyのrelationshipを使用する際には、モデルを読み込む順序は内部で決まっているが、まだUser
モデルを読み込んでいないにもかかわらず、Project
モデルでリレーションを張ろうとしても失敗してしまう、ということを示している。
解決方法
Project
モデルを設定する前に、User
を読み込んであげればよい。
(# noqa
を記述しているのは、Linterエラーに引っかかるのを防ぐため。)
from sqlalchemy import Column, String
from sqlalchemy.orm import relationship
from app.db.base_class import Base
from app.models.project_user import ProjectUser
# from app.models.feature import Feature # noqa # 追加した部分
class Project(Base):
__tablename__ = "projects"
title = Column(String(255), default="", nullable=False)
users = relationship(
"User",
secondary=ProjectUser.__tablename__,
back_populates="projects",
)
project_user = relationship("ProjectUser")