侧边栏壁纸
博主头像
我的学习心得 博主等级

行动起来,活在当下

  • 累计撰写 223 篇文章
  • 累计创建 60 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

Python跨文件的循环引用问题

Administrator
2024-09-05 / 0 评论 / 0 点赞 / 716 阅读 / 0 字

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 仅作为类型导入,它在实际运行时是不存在的,所以对应使用的地方必须使用 字符串注解类型

0

评论区