选择忽略sqlalchemy Mapped Class构造函数中的额外关键字?

mgc*_*nny 6 python orm sqlalchemy

在下面,我尝试从具有额外键的python字典初始化sqlalchemy Mapped类.是否可以让Mapped类自动忽略额外的键而不是抛出错误?同样,如果键不存在,Mapped类是否可以具有默认值?

from sqlalchemy import Column, Integer, String
class User(Base):
     __tablename__ = 'users'

     id = Column(Integer, primary_key=True)
     name = Column(String)
Run Code Online (Sandbox Code Playgroud)

这是init部分:

my_example_user = {'id'=1, 'name'='john', 'extra_key'= 1234}
User(**my_example_user)
Run Code Online (Sandbox Code Playgroud)

这会引发无效的密钥错误

思考?

Eri*_*hli 6

SQLAlchemyMapper对象有一个attrs属性,它是映射类的字段名称的字典。

from sqlalchemy import Column, Integer, String
from sqlalchemy.orm import class_mapper
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()

class User(Base):
    __tablename__ = 'user'

    id = Column(Integer, primary_key=True)
    name = Column(String)

user = {
    'name': 'Eihli',
    'skill': 11
}

user_mapper = class_mapper(User)
mapped_user = User(**user)
# Boom! TypeError: 'skill' is an invalid keyword argument for User

mapped_user = User(**{
    k: v for k, v in user.items()
    if k in user_mapper.attrs.keys()
})
# Success!
Run Code Online (Sandbox Code Playgroud)

无需费心维护排除列表或使用dict或妨碍超级调用。

如果您尝试使用嵌套数据生成模型,则必须做一些不同的事情。否则你会得到一个“Unhashable type 'dict'”错误。

这是一个检查映射器并获取关系键的助手示例。

def from_json(model, data):
    mapper = class_mapper(model)
    keys = mapper.attrs.keys()
    relationships = inspect(mapper).relationships
    args = {k: v for k, v in data.items()
            if k in keys and k not in relationships}
    return model(**args)
Run Code Online (Sandbox Code Playgroud)


uvs*_*tid 5

总之,定义构造函数并没有参数传递到它的超类:

class User(Base):

    # ...

    def __init__(self, **entries):

        # NOTE: Do not call superclass
        #       (which is otherwise a default behaviour).
        #super(User, self).__init__(**entries)

        self.__dict__.update(entries)
Run Code Online (Sandbox Code Playgroud)

我在从peewee过渡时遇到了同样的问题,这需要相反的 - 将参数传递给它的超类(因此,构造函数已经定义)。所以,我只是尝试注释掉这条线,事情就开始奏效了。

更新

此外,请确保entries不包含(并因此覆盖)User为 SQLAlchemy 定义的类中的任何元字段,例如,那些 ORM 关系。这有点明显(SQLAlchemy),但是当出现错误时,发现问题可能并不容易。