在 Python 前向引用的问题 中类 AuditLog
和类 AuditDetail
是直接放置在同一个文件中的,此时可直接通过 字符串注解 来解决循环引用的问题。
如果类 AuditLog
和类 AuditDetail
分别放置在两个文件中,由于外键定义的刚需,我们必须在 audit_detail.py 中全局导入 AuditLog
:
from .audit_log import AuditLog
class AuditDetail(models.Model):
audit_log = models.ForeignKey(AuditLog, on_delete=models.CASCADE, related_name="_details")
如果我们在 audit_log.py 中全局导入 AuditDetail
,就会触发 循环导入 的问题。
最直观的办法是在属性方法内部导入:
class AuditLog(models.Model):
@property
def details(self):
from .audit_detail import AuditDetail
qs: QuerySet[AuditDetail] = self._details.all()
# 同样可以使用字符串注解类型
# qs: QuerySet["AuditDetail"] = self._details.all()
return qs
但是显然,这样的代码不太优雅。
此时可以使用 TYPE_CHECKING
常量可以在类型检查阶段导入类,而在运行时忽略这些导入,从而避免循环导入问题。
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from .audit_detail import AuditDetail
class AuditLog(models.Model):
@property
def details(self) -> QuerySet["AuditDetail"]:
return self._details.all()
@property
def first_detail(self) -> "AuditDetail":
return self.details.first()
此解决方案相当于将 AuditDetail
仅作为类型导入,它在实际运行时是不存在的,所以对应使用的地方必须使用 字符串注解类型。
评论区