RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1601095
Accepted
Irking
Irking
Asked:2024-11-28 18:37:26 +0000 UTC2024-11-28 18:37:26 +0000 UTC 2024-11-28 18:37:26 +0000 UTC

SQLAlchemy 模型之间的并行导入

  • 772

我有一个描述数据模型的模块:

Основные классы:
- ActionType: Таблица-Справочник отслеживаемых действий
- AuditLog: Логирование действий пользователей.
- Assembly: Описание сборочных чертежей.
- Part: Описание деталей.
- AssemblyPart: Связь между сборками и деталями.
- AssemblyAssembly: Связь между сборками и другими сборками.
- Material: Таблица-Справочник материалов.
- Thick: Таблица-Справочник толщин материалов.
- ProgramX5: Программы обработки для станков Х5.
- PartProgramX5: Связь между деталями и программами обработки.
- Role: Таблица-Справочник ролей пользователей.
- User: Пользователи системы.

考虑到这是一个最小的结构,我决定立即将其分为 3 部分:

- модуль с основными моделями (Сборки, детали, пользователи)
- модуль со справочниками (роли, материалы и т.д.)
- модуль связей (все модели, организующие связь многие-ко-многим)

然后我遇到了目录/关系和主模型之间的交叉导入。

这是如何解决的?best practices对SQLAlchemy 的声明式风格感兴趣。

python
  • 1 1 个回答
  • 20 Views

1 个回答

  • Voted
  1. Best Answer
    Alexander Lonberg
    2024-11-29T09:35:20Z2024-11-29T09:35:20Z

    相反,问题是关于“循环”进口而不是“平行”进口。

    如果是这种情况,那么: 一个模块(文件)A无法完成初始化,因为它需要一个依赖模块B,而依赖模块又需要A.这是不可能的,试图解决无法解决的问题也不会成功。

    类型检查

    如果我们谈论导入类型(作为注释),那么这就解决了它TYPE_CHECKING。

    from typing import TYPE_CHECKING
    
    if TYPE_CHECKING:
        from my_module import MyType
    
    def foo(instance: "MyType"):
        data = instance.get_data()
    

    该类型不能显式使用,例如创建该类的实例ins = MyType(),但这并不妨碍您调用其方法并在注释中使用它们。简单地说,解释器中的字符串TYPE_CHECKING将被忽略,但它们对静态分析器是可见的。

    至于库SQLModel/SQLAlchemy,我们使用相同的库TYPE_CHECKING,并且还将对符号的引用括在括号中,例如 SQLModel:

    team: Optional["SomeClass"] = Relationship(back_populates="xyz")
    

    ...就像类名完全未定义时所发生的情况一样:

    class SomeClass:
        def try_get(self) -> "None | SomeClass":...
    

    协议

    对于某些辅助类型,您可以将协议类放在单独的文件中。几乎像一个抽象类,但更灵活一点并且更少依赖于其他模块。这与定义接口非常相似:

    // types.py
    from typing import Protocol
    
    class LoggerProtocol(Protocol):
        def error(self, msg: str) -> None:...
    

    ...然后在任何地方实现这样一个协议类LoggerImpl(不必继承它),但将协议导入到依赖模块中:

    from .types import LoggerProtocol
    
    class MyModule:
        def __init__(self, logger: LoggerProtocol):...
    

    当然,这种方法需要能够创建LoggerImpl并将其传递给依赖模块的方法:

    logger = LoggerImpl()
    my_module = MyModule(logger)
    

    协议的工作方式与类型相同TypeScript:结构类型 - 最主要的是所有属性和方法都在那里,并且作为此类型传递的内容并不重要。

    肮脏的方法

    <pre>(Вместо спойлера которого тут нет)
    На самом деле любую зависимость можно получить налету используя нечто подобное:
    
    ```py
    if TYPE_CHECKING:
        from .my_module import SomeClass
    
    # так
    def create_instance(class_name: str, *args: Any, **kwargs: Any) -> Any:
        module = importlib.import_module("my_project.my_module")
        cls = getattr(module, class_name)
        return cls(*args, **kwargs)
    
    # ... или так
    def createSomeClass() -> "SomeClass":
        from .my_module import SomeClass
        return SomeClass()
    ```
    
    ... но это хорошо для условных `if sys.platform == "win32"`, а не круговых зависимостей. 
    Такие фокусы с круговыми зависимостями приведут к повторному выполнению кода модуля.
    </pre>

    聚苯乙烯

    大多数情况下,这样的方法足以解决循环依赖,但我不知道SQLAlchemy中的最佳实践TYPE_CHECKING/Interface-Protocol是什么。

    PPS:有时,在一个文件中保留 1000 行会更容易,而无需发明不必要的文件名,也无需解决循环依赖问题。

    • 1

相关问题

  • 是否可以以某种方式自定义 QTabWidget?

  • telebot.anihelper.ApiException 错误

  • Python。检查一个数字是否是 3 的幂。输出 无

  • 解析多个响应

  • 交换两个数组的元素,以便它们的新内容也反转

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5