在FastAPI中避免循环导入

后端开发 2026-07-10

我正在学习FastAPI,并计划把应用按如下结构组织:

app in FastAPI:

  • models.py文件,用于存放数据库以及其他重要的Python相关方法
  • routes.py文件,用于放置路由(URL)
  • schemas.py文件,用于按路由需要存放不同的数据模式

现在我创建了一个名为users的应用及其模型,如下所示

class User(Base):
    __tablename__ = "users"

    id: Mapped[int | None] = mapped_column(Integer, primary_key=True, default=None)  # autoincrement=True
    username: Mapped[str] = mapped_column(String(50), unique=True, nullable=False)
    email: Mapped[str] = mapped_column(String(120), unique=True, nullable=False)
    hashed_password: Mapped[str] = mapped_column(String(200), nullable=False)

    profile: Mapped[Profile] = relationship("Profile", back_populates="user", uselist=False)


class Profile(Base):
    __tablename__ = "profiles"

    id: Mapped[int | None] = mapped_column(Integer, primary_key=True, default=None)
    user: Mapped[User] = relationship("User", back_populates="profile")
    user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), nullable=False, index=True)

    paied_until: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False
    )
    from_phone: Mapped[str | None] = mapped_column(String(20), nullable=True, default=None)
    messages: Mapped[list[WAMessage]] = relationship(back_populates="profile", cascade="all, delete-orphan")

注意,这里我与WAMessage之间存在关联,由于Mapped的原因,我必须把该类加入其中。

现在在另一个文件夹中的WAMessage.models,我添加了如下代码

class WAMessage(Base):
    __tablename__ = 'wa_messages'

    status: Mapped[str] = mapped_column(String(9), nullable=False, default=WAMessageStatusChoices.waiting)
    attachment_file: Mapped[str | None] = mapped_column(String(200), nullable=True, default=None)
    content: Mapped[str] = mapped_column(Text, nullable=False)
    user_id: Mapped[str] = mapped_column(ForeignKey("profiles.id"), nullable=False, index=True)
    profile: Mapped[Profile] = relationship(back_populates="messages")

而且使用这个文件时,我遇到了循环导入的错误,我认为还会有很多其他需要与用户建立关系的表。

在使用Django时,有一个辅助函数 from django.contrib.auth import get\_user\_model,它可以接受用户应用的字符串位置,从而导入它,而不使用AUTH_USER_MODEL="users.User"。但这个函数对我来说有点难以理解,但也许有人能找到从字符串获取模型的方法(这会非常有用)

否则

是否有办法解决这个循环导入问题

解决方案

使用 字符串类型+ TYPE_CHECKING,不要在运行时导入模型。

users/models.py

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from app.wa_messages.models import WAMessage

class Profile(Base):
    __tablename__ = "profiles"

    messages: Mapped[list["WAMessage"]] = relationship(
        "WAMessage", back_populates="profile", cascade="all, delete-orphan"
    )

wa_messages/models.py

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from app.users.models import Profile

class WAMessage(Base):
    __tablename__ = "wa_messages"

    profile: Mapped["Profile"] = relationship(
        "Profile", back_populates="messages"
    )
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章