-
-
Notifications
You must be signed in to change notification settings - Fork 724
Cyclic import error with Multiple files #1358
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I solved this cyclic import problem by moving the import to the end of the file and calling pydantic's model_rebuild method. You can read more in the Pydantic docs |
Hi @bentoluizv, thank you, your solution works, but in my case it is used many-to-many, and at this point an error occurs. I have 3 files, each of which has models. from models.link_models import ServiceQualificationLink class Service(SQLModel, table=True): from models.qualifications import Qualification from models.link_models import ServiceQualificationLink class Qualification(SQLModel, table=True): from models.services import Service from sqlmodel import Field, SQLModel class ServiceQualificationLink(SQLModel, table=True): If I have a commented out link_model string, then I get the following error: sqlalchemy.exc.InvalidRequestError: When initializing mapper Mapper[Qualification(qualifications)], expression "relationship("list['Service']")" seems to be using a generic class as the argument to relationship(); please state the generic argument using an annotation, e.g. "service: Mapped[list['Service']] = relationship()" If this field is not commented out, then the error is already like this: sqlalchemy.exc.InvalidRequestError: One or more mappers failed to initialize - can't proceed with initialization of other mappers. Triggering mapper: 'Mapper[Qualification(qualifications)]'. Original exception was: When initializing mapper Mapper[Qualification(qualifications)], expression "relationship("list['Service']")" seems to be using a generic class as the argument to relationship(); please state the generic argument using an annotation, e.g. "service: Mapped[list['Service']] = relationship()" Here are the versions of the libraries that I use: |
As you rightly mentioned: And that is why while annotating qualification here: qualification: list["Qualification"] You have defined Qualification as a literal string by adding quotation marks "Qualification" However, when accessing the link_model - ServiceQualificationLink - in Relationship, you have not defined it as a literal string. To resolve your issue, have it as: qualification: list["Qualification"] = Relationship(
back_populates="service",
link_model="ServiceQualificationLink"
) and that should solve your issue. I reproduced your previous code hero example as follows and it worked perfectly: team.py from typing import TYPE_CHECKING
from sqlmodel import Relationship, SQLModel, Field
if TYPE_CHECKING:
from .hero import Hero
from .link import HeroTeamLink
class Team(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
name: str
heroes: list["Hero"] = Relationship(
# secondary="hero",
back_populates="team",
link_model="HeroTeamLink",
) hero.py from typing import TYPE_CHECKING
from sqlmodel import Relationship, SQLModel, Field
if TYPE_CHECKING:
from .team import Team
from .link import HeroTeamLink
class Hero(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
name: str
teams: list["Team"] = Relationship(back_populates="hero", link_model="HeroTeamLink") link.py from sqlmodel import SQLModel, Field
class HeroTeamLink(SQLModel, table=True):
hero_id: int = Field(foreign_key="hero.id", primary_key=True)
team_id: int = Field(foreign_key="team.id", primary_key=True) |
Hi @Kahacho, thank you for your help. I used your code examples, but I got the following error: Traceback (most recent call last): Here are the code examples: from typing import TYPE_CHECKING if TYPE_CHECKING: class Hero(SQLModel, table=True): *_*_*_*_*__* team.py from typing import TYPE_CHECKING if TYPE_CHECKING: class Team(SQLModel, table=True): *_*_*_*_*__* link.py from sqlmodel import SQLModel, Field class HeroTeamLink(SQLModel, table=True): Can you tell me your library versions and what could I have reproduced wrong? |
In your from typing import TYPE_CHECKING
if TYPE_CHECKING:
from team import Team
from hero import Hero |
@Kahacho, thanks a lot, it solved my problem. |
@sebastianfym Glad it worked out. |
Privileged issue
Issue Content
At the moment, if you split the model file into different folders, the cyclic import error will appear.
Decision:
from future import annotations
if TYPE_CHECKING:
from models.general_name_models import Model1, Model2
it did not produce results, because when accessing models imported under if TYPE_CHECKING, they are considered strings, and in this case, the Relationship does not work.
Therefore, in order for all the imports to work adequately and there were no problems with requests, we had to remove all the Relationship's.
If all the Relationships are removed, then the project starts and even functions (partially), but in this case we will have to rewrite most of the functions from db , since in many places we join as follows (example):
joinedload(Team.hero)
This query won't work because the Team model won't see the hero attribute.
Otherwise, if you don't choose a Relationship (for example, a team.hero), you can get them yourself:
sqlalchemy.exc.InvalidRequestError: When initializing mapper Mapper[Hero(hero)] the expression "relationship("list['Team']")" appears to use a common class as an argument for relationship(); please specify a common argument using an annotation, such as "team: Mapped[list['Team']] = communication()"
Below are some examples of my code.
link.py:
class HeroTeamLink(SQLModel, table=True):
hero_id: int = Field(foreign_key="hero.id", primary_key=True)
team_id: int = Field(foreign_key="team.id", primary_key=True)
###############################################################
team.py:
from future import annotations
from typing import TYPE_CHECKING
from sqlmodel import (
Relationship,
SQLModel,
)
if TYPE_CHECKING:
from models.hero import Hero
class Team(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
name: str
heroes: list["Hero"] = Relationship(
# secondary="hero",
back_populates="team",
link_model=HeroTeamLink,
)
###############################################################
hero.py:
from future import annotations
from typing import TYPE_CHECKING
from sqlmodel import (
Relationship,
SQLModel,
)
if TYPE_CHECKING:
from models.team import Team
from models.link import HeroTeamLink
class Hero(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
name: str
teams: list["Team"] = Relationship(
back_populates="hero", link_model=HeroTeamLink
)
###############################################################
The text was updated successfully, but these errors were encountered: