首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我应该为SQLalchemy declarative_base使用哪种类型?

我应该为SQLalchemy declarative_base使用哪种类型?
EN

Stack Overflow用户
提问于 2019-10-10 22:39:31
回答 2查看 771关注 0票数 4

我想为我的SQLAlchemy基类使用类型,但似乎找不到类型定义。

例如:

代码语言:javascript
复制
from sqlalchemy.types import BigInteger
from sqlalchemy.schema import Column, Index
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class User(Base):

    __tablename__ = "users"

    id_user = Column(
        BigInteger, primary_key=True, autoincrement=True, nullable=False, index=True
    )
    username = Column(String, unique=True, index=True)

现在,当引用这个User类时,我不知道该使用哪种类型。此外,如果我想拥有一个包含table_name :模型映射的字典,如下所示:

代码语言:javascript
复制
from typing import Any, Dict

table_model_map: Dict[str, Any] = {
    "users": User,
    "another_table": AnotherTableModel,
}

我该如何定义这个字典的类型?

非常感谢你帮我理解这一点!

EN

回答 2

Stack Overflow用户

发布于 2019-10-17 12:06:41

Base是所有模型(也是类型)都继承的类型,因此

代码语言:javascript
复制
Dict[str, Base]
票数 0
EN

Stack Overflow用户

发布于 2021-06-03 16:25:37

Ilja是正确的,因为如果你所有的模型类都是Base的子类,这是一个适合输入提示你的字典的选项。

但是,如果您想在创建之前键入将Base作为参数接收的提示内容,即如下所示:

代码语言:javascript
复制
class DatabaseJanitor:
    def __init__(self, base: WhatTypeHere?, engine):
        self._base = base
        self._engine = engine

    def create_metadata(self):
        self._base.metadata.create_all(self._engine)

这就有点棘手了。我做了一些挖掘,这是我为sqlalchemy-1.4.17找到的。

sqlalchemy/orm/decl_api.py中可以看到以下内容

代码语言:javascript
复制
class DeclarativeMeta(type):
    def __init__(cls, classname, bases, dict_, **kw):
        ...

def declarative_base(
    ...
    metaclass=DeclarativeMeta,
):
    ...
    return registry(
        _bind=bind,
        metadata=metadata,
        class_registry=class_registry,
        constructor=constructor,
    ).generate_base(
        mapper=mapper,
        cls=cls,
        name=name,
        metaclass=metaclass,
    )

class registry(object):
    ...
    def generate_base(
        ...
        metaclass=DeclarativeMeta,
    ):
        metadata = self.metadata

        bases = not isinstance(cls, tuple) and (cls,) or cls

        class_dict = dict(registry=self, metadata=metadata)
        if isinstance(cls, type):
            class_dict["__doc__"] = cls.__doc__

        if self.constructor:
            class_dict["__init__"] = self.constructor

        class_dict["__abstract__"] = True
        if mapper:
            class_dict["__mapper_cls__"] = mapper

        return metaclass(name, bases, class_dict)

因此,declarative_base将返回传入的metaclass关键字参数的一个实例。因此,Base = declarative_base(metaclass=MyNewMetaclass)将导致type(Base) == MyNewMetaclass

此外,正如您在registry.generate_base中看到的,元类的新实例(如metadata)的所有属性都包含在class_dict中。这些属性在创建期间作为属性隐式添加到实例中,因此它们在类型提示期间不可用。

(旁注:我做了一些研究,似乎因为DeclarativeMetatype的子类,所以type.__new__被隐式调用,然后将class_dict字典中的值作为属性添加到DeclarativeMeta的实例中。我将在本答案的末尾链接一些资源以供进一步阅读。)

所以,即使你像这样输入hint你的函数:

代码语言:javascript
复制
class DatabaseJanitor:
    def __init__(self, base: DeclarativeMeta, engine):
        self._base = base
        self._engine = engine

    def create_metadata(self):
        self._base.metadata.create_all(self._engine)

create_metadata中,您的类型提示将警告Unresolved attribute reference 'metadata' for class 'DeclarativeMeta'

所以没有一个很好的方法来正确地输入提示declarative_base。我的方法是暂时将其添加到文档字符串中。

希望这对任何未来的读者都有帮助!:)

下面是一些关于类型/元类的进一步阅读:

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58325495

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档