Python, 模型<>模型, 如何避免循环导入



假设我有一个pydantic(它可以是任何类型)模型,它应该知道如何将自己转换为form(它可以是任何类型)模型。为此,我构造了mod_a.py:

from pydantic import BaseModel
from mod2mod.mod_b import DBUser
class User(BaseModel):
name: str
surname: str
def to_orm(self) -> DBUser:
return DBUser(
full_name = f"{self.surname},{self.name}"
)

我也希望我的form模型能够将自己转换为pydantic模型,所以我的mod_b.py是:

from sqlalchemy.orm import declarative_base
from sqlalchemy import Column, Integer, String
from mod_a import User
Base = declarative_base()
class DBUser(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
full_name = Column(String)
def to_pydantic(self) -> User:
surname, name = self.full_name.split(',')
User(
name=name,
surname=surname
)

想法是能够从一个模型到另一个模型随意像mod2mod.py:

import pydantic
from mod_a import User
from mod_b import DBUser

user = User(name='John', surname='Doe')
orm_user = user.to_orm()
pydantic_user = orm_user.to_pydantic()
print(user)
print(pydantic_user)

显然这行不通,因为:

ImportError: cannot import name 'User' from partially initialized module 'mod_a' (most likely due to a circular import) (/mod2mod/mod_a.py)

如何解决这类问题?我是否需要另一个实体,现在将如何做模型之间的转换,并把当前的模型方法在那里或有一些其他的设计模式?

您可以使用import ...样式代替from ... import ...。并将返回类型提示括在引号中(我在下面这样做)或使用延迟的注释求值PEP-563(顺便说一下,这是Python 3.10的默认值)

# mod_a.py
from pydantic import BaseModel
import mod_b

class User(BaseModel):
name: str
surname: str
def to_orm(self) -> 'mod_b.DBUser':
return mod_b.DBUser()
# mod_b.py
import mod_a
class DBUser:
def to_pydantic(self) -> 'mod_a.User':
return mod_a.User(
name="",
surname=""
)

您必须执行本地import和我们的TYPE_CHECKING才能执行类型提示。

from typing import TYPE_CHECKING
from pydantic import BaseModel
if TYPE_CHECKING:
from mod2mod.mod_b import DBUser

class User(BaseModel):
name: str
surname: str
def to_orm(self) -> "DBUser":
from mod2mod.mod_b import DBUser
return DBUser(
full_name = f"{self.surname},{self.name}"
)

DBUser也这样做。

最新更新